异常捕获的基本流程
public class Main {
public static void main(String[] args) {
int[] array=new int[1];
int a=10,b=0;
//除法异常被第一个catch捕获
try{
a=a/b;
}catch (ArithmeticException e){
System.out.println("arithmeticException1");
e.printStackTrace();
}catch (Exception e){
System.out.println("Exception");
e.printStackTrace();
}finally {
System.out.println("finally1");
}
//数组越界异常没被捕获
try{
System.out.println(array[2]);
}catch (ArithmeticException e){
System.out.println("arithmeticException2");
e.printStackTrace();
}finally {
System.out.println("finally2");
}
System.out.println("hello world");
}
}
运行结果:
arithmeticException1
finally1
finally2
java.lang.ArithmeticException: / by zero
at Main.main(Main.java:20)
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at Main.main(Main.java:33)
上面的例子得出的结论:
1.一个异常被某一个catch块捕获之后,就不会访问下一个catch,而是直接到finally,再执行后面的代码。就好比方法重载,哪个参数是该异常属于的类(如果有两个catch块的两个参数都是该异常属于的类,一个是父类异常,一个是子类异常,那么选子类异常),就被哪个catch块执行。
2.一个异常没有被任何一个catch块捕获的话,就会交由JVM进行默认处理(输出异常信息),不再执行后面的代码。
如果catch块中又抛出了异常,而且该异常未被捕获,则直接执行完finally后,不再执行后面的代码。
System.out.println("除法计算开始");
try{
int result=x/y;
}catch (Exception e){
throw e;
}
finally {
System.out.println("除法计算结束");
}
System.out.println("hello world");
运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
除法计算开始
除法计算结束
并不会打印“hello world”。
程序运行时,任何地方若抛出异常后,该异常没有被捕获,则后面的代码(除了finally语句块中的)都将不会再执行。
运行时异常和编译时异常
1.运行时异常:当某行代码抛出运行时异常,程序员可以不用捕获或者声明;或者当某行代码调用一个会抛出运行时异常的方法,也可以不用捕获或者声明。
2.编译时异常:当某行代码抛出编译时异常,程序员必须捕获或者声明;或者当某行代码调用一个会抛出运行时异常的方法,也必须捕获或者声明。
为什么要区分运行时异常和编译时异常?
网友的回答:https://www.iteye.com/problems/99135
抛出异常的话要在方法名后面声明吗?
有时候我们会看到一些方法名后面会throws 一些异常以声明,有时候又没有。当然了,如果是编译时异常,并且没有try...catch的话肯定是需要声明的。那其他情况呢?
网友的回答:声明的好处是调用此方法的对象知道这个方法可能会出现这种异常,并进行处理。RuntimeException在很多时候并不清楚会发生什么异常,所以一般情况下没有必要写,也很难写全。从功能上说,加不加都是可以. 从远的方向想,如果发布为doc,就提示调用者可能抛出什么异常。
子类继承父类时要注意的异常
子类重写父类方法时,子类声明的异常不能比父类声明的异常大。也就是说,父类方法throws的异常要涵盖子类方法throws的异常。