Java_异常(9)

异常

异常机制是当程序发生异常时强制终止程序运行并 new 一个异常对象交给异常处理程序

try 代码块包含的是被监听的代码,如果检测到有异常,则将异常交给 catch 代码块,即捕获异常

finally 主要用于释放资源,除了中途直接关闭 JVM ,只要执行了其对应的 try,则 finally 一定会执行,即使在 try 或 catch 中执行了 return 或 throw,finally 还是会执行,对于返回值,若 finally 中有 return,则会用 finally 中 return 的值覆盖在 try、catch 中 return 的值

throw 是操作,抛出异常并将程序控制交给其调用者,throws 是方法声明,表示该方法可能抛出异常

Throwable 异常接口有 Error 和 Exception 两个子类,而 RuntimeException 是 Exception 的子类

Exception 类及其子类 (除了运行时异常) 属于被检查异常,编译器会检查,要么声明 throws 抛出异常,要么在内部通过 try catch 捕获处理,否则不能通过编译,常见的例如 IOException,CloneNotSupportedException

RuntimeException 及其子类属于运行时异常,如果触发会时程序中断,需要通过改进代码实现来避免,编译器不会检查,可以通过 throws 声明抛出,也可以在内部 try catch 捕获,常见的例如 ArithmeticException、 NullPointerException、IndexOutOfBoundsException、ConcurrentModificationException

Error 及其子类属于错误,编译器不会检查,一般是 JVM 运行出错,常见的例如 OutOfMemoryError

经典问题,NoClassDefFoundError 和 ClassNotFoundException 有什么区别 NoClassDefFoundError 是 JVM 加载某个类没有找到抛出的错误 ClassNotFoundException 是调用 Class.forName() 加载类没有找到抛出的异常

try、catch

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class Test {
  public static void main(String[] args) {
    int[] arr = {1, 2, 3};
    try {
      System.out.println(10 / 0);
      //10 / 0出错直接跳到catch,try中剩余的代码就不再执行了
      System.out.println(arr[10]);
    } catch (ArithmeticException e) {
      System.out.println("异常:除数为0了");
    } catch (ArrayIndexOutOfBoundsException e) {
      System.out.println("异常:索引越界了");
    } catch (Exception e) {
      System.out.println("出错了");
    }
    //根据多态原理,如果有多个catch,小的放前面,大的放后面
    System.out.println("catch了异常可以继续执行后续代码");
  }
}

jdk 7 引入了处理多个异常

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class Test {
  public static void main(String[] args) {
    int[] arr = {1, 2, 3};
    try {
      System.out.println(10 / 0);
      System.out.println(arr[10]);
    } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
      System.out.println("出错了");
    }
  }
}

finally

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Test {
  public static void main(String[] args) {
    try {
      System.out.println(10 / 0);
    } catch (Exception e) {
      System.out.println("除数为0了");
      //System.exit(0); //退出java虚拟机,finally将不会执行
      return;
    } finally {
      System.out.println("执行finally");
    }
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Test {
  public static void main(String[] args) {
    System.out.println(print()); //8
  }
  public static int print() {
    //if (true) {  //如果在执行try之前就返回了,则finally也不会执行
    //  return 0;
    //}
    int x = 10;
    try {
      System.out.println(1 / 0);
      return x; //触发异常,这里的return不执行,进入catch
    } catch (Exception e) {
      x--;
      System.out.println(x); //9
      return x--; //复制x的值9返回,--操作这里不执行
    } finally {
      //先对x执行catch中return未执行的--操作
      System.out.println(x); //8
      return x--; //复制x的值8覆盖catch中return的x的值9,--操作这里也不执行
    }
  }
}

throw、throws

运行时异常 RuntimeException 默认向其调用者抛出,也可以通过 throw 手动抛出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class Test {
  public static void main(String[] args) {
    try {
      print();
    } catch (Exception e) {
      System.out.println(e);
      //java.lang.ArithmeticException: / by zero
    }
  }
  public static void print() {
    try {
      System.out.println(10 / 0);
    } catch (ArithmeticException e) {
      throw e; //只能抛出一个异常对象
    }
  }
}

throws 用作声明方法可能会抛出异常

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class Test {
  public static void main(String[] args) {
    try {
      print();
    } catch (Exception e) {
      System.out.println(e);
      //java.lang.ArithmeticException: / by zero
    }
  }
  //throws可以跟多个异常类名,逗号隔开,没有先后顺序
  public static void print() throws ArithmeticException, Exception {
    System.out.println(10 / 0);
  }
}

在多态时,子类重写父类方法,如果父类方法声明了抛出异常,则子类也要抛出异常,且抛出的异常必须与父类抛出的异常相同或是其子类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class Test {
  public static void main(String[] args) {
    S s = new S();
    try {
      s.print();
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}
class F {
  public void print() throws Exception {}
}
class S extends F {
  @Override
  public void print() throws ArithmeticException {
    System.out.println(10 / 0);
  }
}

如果父类方法没有声明抛出异常,则需要子类自己进行 try catch 处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test {
  public static void main(String[] args) {
    F f = new S();
    f.print();
  }
}
class F {
  public void print() {
    System.out.println(10 / 0);
  }
}
class S extends F {
  @Override
  public void print() {
    try {
      System.out.println(10 / 0);
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}

以上内容是玉山整理的笔记,如有错误还请指出