JavaSE核心API--异常类

java.lang.Exception

1)理论讲解:自动关闭

JDK1.7之后推出了一个新的特性:自动关闭
使用该特性,对于IO操作后的关闭变得比较简单了。

代码演示:

    try(
        /*
         * JDK1.7之后提供了一个接口:AutoCloseable
         * 实现了该接口的类可以在此定义,最终会在finally中被关闭(编译器会在编译后改变代码)
         */
        FileOutputStream fos
            = new FileOutputStream("fos.dat");
    ){  
        fos.write(1);
    } catch (Exception e) {
        System.out.println("出错了!");
    }   

2)理论讲解:异常常用方法

代码演示:

    System.out.println("程序开始了!");
    try {
        String str="a";
        System.out.println(Integer.parseInt(str));//该行代码出错--at exception.ExceptionApiDemo.main(ExceptionApiDemo.java:11)
        System.out.println("helloWorld");
    } catch (Exception e) {
        System.out.println("出错啦!");
        //调用printStackTrace()方法输出错误堆栈信息,有助于我们解决错误,去找到at我们写的那个类
//      e.printStackTrace();//这个是最常用的
        String message=e.getMessage();
        System.out.println(message);//结果输出For input string: "a"---告知用户因为你输入的是字符串a,不能转成整型数字
    }
    System.out.println("程序结束了!");

3)理论讲解:finally块

finally块
finally是异常处理机制的最后一块。它可以直接跟在try语句块之后,或者最后一个catch块之后。
finally能确保只要程序执行到try语句块中,无论try语句块中的代码是否抛出异常,finally块中的代码必定执行。
通常会将无关乎程序出错都要执行的代码放在这里,比如资源的释放操作:IO里的流关闭。

代码演示:

    System.out.println("程序开始了");        
    try {
        String str = "";
        System.out.println(str.length());
        return;
    } catch (Exception e) {
        System.out.println("出错了!");
    } finally {
        System.out.println("finally中的代码执行了!");
    }
    System.out.println("程序结束了");

4)理论讲解:finally在IO中的使用

代码演示:

    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream("fos.dat");
        fos.write(1);           
    } catch (Exception e) {
        System.out.println("出错了");
    } finally {
        try {
            if(fos!=null) {
                fos.close();
            }
        } catch (IOException e) {
        } 
    }

5)理论讲解:finally常见笔试题

finally常见笔试题
1:下面的代码

2:请分别说明:final,finally,finalize?

finalize方法是Object中定义的方法,当一个对象即将被GC释放时,GC会调用该方法。调用后即被GC释放。
通常我们不会重写这个方法,若需要在一个对象被释放前做某些操作时可以重写该方法。
但是注意!该方法不应当包含耗时的操作。否则会影响GC的回收工作。

代码演示:

public static void main(String[] args) {
    System.out.println(
        test("0")+","+test(null)+","+test("")   
    );
    //3,3,3
}

@SuppressWarnings("finally")
public static int test(String str) {
    try {
        System.out.println("test:"+str);
        return str.charAt(0)-'0';
    } catch (NullPointerException e) {
        System.out.println("空指针");
        return 1;
    } catch (Exception e){
        System.out.println("其他异常");
        return 2;
    } finally {
        System.out.println("test:"+str+",finally执行了!");
        return 3;
    }
}

6)理论讲解:自定义异常

自定义异常
通常自定义异常是用来说明业务逻辑错误。
年龄不合法异常
当年龄超过取值范围时,会抛出该异常。

代码演示:

public class IllegalAgeException extends Exception{//年龄不合法异常
   /**声明序列化版本号*/
   private static final long serialVersionUID = 1L;
   /**从父类中添加构造方法*/
   public IllegalAgeException() {
        super();
        // TODO Auto-generated constructor stub
   }
   public IllegalAgeException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
        super(arg0, arg1, arg2, arg3);
        // TODO Auto-generated constructor stub
   }
   public IllegalAgeException(String arg0, Throwable arg1) {
        super(arg0, arg1);
        // TODO Auto-generated constructor stub
   }
   public IllegalAgeException(String arg0) {
        super(arg0);
        // TODO Auto-generated constructor stub
   }
   public IllegalAgeException(Throwable arg0) {
        super(arg0);
        // TODO Auto-generated constructor stub
   }
}

7)理论讲解:使用当前类测试异常的抛出

代码演示:

public class Person {
   private int age;

   public int getAge() {
        return age;
   }

   /**
     * 通常一个方法中通过throw抛出什么异常,就要在方法声明的同时使用throws声明该异常的抛出
     * 当一个方法声明了异常抛出后,那么当调用该方法时编译器会要求调用的代码片段必须处理该异常
     * 注:只有方法中抛出RuntimeException及其子类型异常时,可以不用在方法声明时使用throws声明该类异常的抛出
     * 
     * @param age
     * @throws ExceptionDemo
     */
   public void setAge(int age) throws IllegalAgeException {// throws用于告知调用者该方法有异常需要处理
        if (age < 0 || age > 100) {
           throw new IllegalAgeException("年龄不合法!");// throw用于抛异常
        }
        this.age = age;
   }
}

8)理论讲解:异常的抛出

异常的抛出
throw关键字用于将一个异常抛出------通常遇到以下情况我们会主动在一个方法中抛出异常:
1.程序运行时出现了一个异常,但是该异常不应当在当前方法中被解决时,可以给调用者处理
2.程序运行时出现了不符合业务逻辑的情况时,可以主动实例化一个异常抛出给调用者告知其这样的调用不合理----java没有提供,要自定义异常(见名知意)

代码演示:

public static void main(String[] args) {//不能在main方法用throws
    Person p=new Person();
    try {
        /*
         * 当我们调用一个含有throws声明异常抛出的方法时,编译器要求我们必须处理该异常,否则编译不通过
         * 处理异常的手段有两种:
         * 1.使用try-catch捕获该方法throws声明抛出的异常-----应该归我管则处理
         * 2.在当前方法上继续使用throws声明该异常的抛出-------不归我管则继续往外抛
         */
        p.setAge(1000);//调用抛异常的方法的同时必须要用try-catch处理该异常
    } catch (IllegalAgeException e) {
        e.printStackTrace();
//      System.out.println("出错啦!");
    }
    System.out.println(p.getAge());
}

9)理论讲解:重写含有throws声明异常抛出的方法时对throws的重写准则

代码演示:

public class ThrowsDemo {
public void dosome() throws IOException,AWTException {}
}
class Boo extends ThrowsDemo{
//  @Override
//  public void dosome() throws IOException,AWTException {}

//  /**
//   * 可以仅抛出超类方法的部分异常
//   */
//  @Override
//  public void dosome() throws IOException {}

//  /**
//   * 可以不再抛出任何异常
//   */
//  @Override
//  public void dosome(){}

//  /**
//   * 可以抛出超类方法的部分异常中的子类型异常
//   */
//  @Override
//  public void dosome() throws FileNotFoundException {}//FileNotFoundException虽然超类方法中没有,但它是IOException的子类

//  /**
//   * 不可以抛出额外异常
//   * 即:超类中没有的异常,并且也没有继承关系的异常
//   */
//  public void dosome() throws SQLException{}

/**
  * 方法的重写:----重新写,覆盖
  *         1)发生在父子类中,方法签名一样(方法名称相同,参数列表相同),方法体不同
  *         2)重写方法被调用时,看对象的类型
  *         3)遵循“两同两小一大”原则:------了解
  *             3.1)两同:
  *                 3.1.1)方法名称相同
  *                 3.1.2)参数列表相同
  *             3.2)两小:
  *                 3.2.1)派生类方法的返回值类型小于或等于超类方法的
  *                 1)void时,必须相等
  *                     2)基本类型时,必须相等
  *                     3)引用类型时,小于或等于
  *                 3.2.2)派生类方法抛出的异常小于或等于超类方法的-----异常之后讲
  *             3.3)一大:
  *                 3.3.1)派生类方法的访问权限大于或等于超类方法的-----明天上午讲
  */

//  /**
//   * 不允许抛出超类方法的部分异常中的父类型异常-----派生类方法抛出的异常小于或等于超类方法的
//   */
//  public void dosome() throws Exception{}//Exception虽然超类方法中没有,但它是IOException的父类
}

10)理论讲解:java异常处理机制中的try-catch

java异常处理机制中的try-catch

try{
   可能出现异常的代码片段
}catch(XXXException e){
   当出现了XXXException后的处理代码
}

代码演示:

    System.out.println("程序开始了");
    try {
//      String str = null;
//      String str = "";
        String str = "a";
        /*
         * 当JVM执行过程中出现某个异常时会实例化对应的异常实例,并将程序执行过程设置进去。
         * 这时该异常实例可以完整说明当前情况。
         * 实例化完毕后,JVM会将该异常抛出
         */
        System.out.println(str.length());

        System.out.println(str.charAt(0));

        System.out.println(Integer.parseInt(str));

        // try语句块中出错代码以下的内容都不会执行
        System.out.println("!!!!!");
    } catch (NullPointerException e) {
        System.out.println("出现了空指针!");

    } catch (StringIndexOutOfBoundsException e) {
        System.out.println("字符串下标越界了!");
        /*
         * 通常会在最后一个catch中捕获Exception,防止 因为一个未捕获的异常导致程序中断
         */
    } catch (Exception e) {
        System.out.println("反正就是出了个错!");
    }
    System.out.println("程序结束了");