前言
这里主要记录java异常处理中比较不常见但可能需要知道的一些问题。接下来我会复习一遍java的异常处理机制并且深入讲解异常处理中的种种问题,比如:异常丢失和异常链
深入解析java异常处理
java异常处理
//捕获异常块
try{
.....
}
//异常处理块
catch(Exception e){
.....
}
//一定会执行的部分(事实并不是一定会执行,特例会在下面介绍)
finally{
.....
}
其中被try包围的代码块是接收检测的代码块,这部分代码可能会抛出异常,JVM虚拟机要求java中的异常一定要被捕获或向外抛出(运行时异常可以不声明捕获。在JVM中异常处理是采用异常表完成,异常表是记录了异常位置和跳转信息的表)
catch块必须紧跟在try块之后,用于处理try块中检测到的异常,它有一个参数用于接收异常,你也可以使用多个catch块接收可能会出现的异常,不够异常会优先被最前面的处理块接收,只要符合参数类型不限数量,所以如果你使用Exception来接收异常一定要写在最后一条处理块中。
你可以在catch块中处理异常(例如使用e.printStackTrace()),也可以再catch块中使用throw e将异常向上抛出。
注*:printStackTrace()方法时打印出异常的栈轨迹,也可以使用getStackTrace()方法来获得包含异常栈轨迹的数组,其中每一个元素都表示栈的一帧(JVM虚拟机在运行一个方法时会产生一个栈帧)其中元素0是栈顶元素,也就是最后一个被调用的方法信息。
在catch中抛出异常
如果在catch块中直接将异常抛出,那么在后面接收到这个异常的程序中,调用printStackTrace()方法,得到的将是原始的异常调用栈信息。如果你想将抛出点设为新的异常信息记录点。可以调用fillInStackTrace()方法
异常链
只有Exceptoin、Error、RuntimeException三个类有带 throwable cause参数的构造器。
所以我们通常使用initCause()方法来链接异常。
initCause方法接收一个throwable参数。
例:
Exception e = new Exception;
e.initCause(catchException);
throw e;
这里假设catchException是捕获到的异常,那么在后来接收到异常e时,使用printStackTrace()方法会有以下结果:
Exception
e的异常栈
Cause by:catchException的类型
catchException的异常栈
在return中使用finally
try{
......
return;
}finally{
System.out.println("执行");
}
上述写法,如果try中没发生异常。finally仍然会在return前执行
异常丢失
1:
try{
try{
throw new ImportantException();
}finally{
throw new NotImportantException();
}
}catch(Exception e){
System.out.println(e);
}
上述代码中,catch块只能捕捉到NotImportantException,而ImportantException丢失了。
2:在finally中return
try{
throw new Exception();
}finally{
return;
}
此时,try块中抛出的异常就被丢失了
最后
我们应该尽量避免写出这样五花八门的代码,但当出现问题时要知道该怎么去解决它。
再提一点:当覆盖方法的时候,只能抛出在基类方法的异常说明列的那些异常或其子类,这么设计是为了使当基类使用的代码应用到派生类的时候,一样能正常的工作。