重新抛出异常:
如果你想把刚捕获的异常扔给上一级处理,尤其是在使用Exception捕获所有异常的时候,既然已经得到了对当前异常对象的引用,可以直接把它重新抛出。重新抛出会把异常抛给上一级环境中的异常处理程序,同一个try块的后续catch子句将被忽略,但finally块不会。此外,异常对象的所有信息都得以保持,所以高一级环境中捕获此异常的处理程序可以从这个异常对象中得到所有信息。
1 package 异常.Finally; 2 3 import java.io.IOException; 4 5 public class ReThrow { 6 7 public static void main(String[] args) { 8 try { 9 test(); 10 } catch (Exception e) { 11 e.printStackTrace(); 12 } 13 } 14 15 public static void test() throws Exception { 16 try { 17 throw new IOException(); 18 }catch(Exception e) { 19 throw e;//向上抛出异常 20 } 21 } 22 23 }
控制台:
java.io.IOException at 异常.Finally.ReThrow.test(ReThrow.java:17) at 异常.Finally.ReThrow.main(ReThrow.java:9)
不必去担心异常对象的清理,它们都是在堆上new出来的,所以gc会把它们回收掉。
异常链:
常常会想要在捕获一个异常后抛出另一个异常,并且希望把原始的异常保存下来,这被称为异常链。在jdk1.4之后,所有的Throwable的子类在构造器中都可以接受一个cause(因由)对象作为参数,这个cause就用来表示原始异常,这样通过把原始异常传递给新的异常,使得即使在当前位置创建并抛出了新的异常,也能通过这个异常链追踪到异常发生的最初位置。在Throwable的子类中,只有三种基本的异常类提供了带参cause参数的构造器,它们是Error,Exception,RuntimeException。如果要想把其他类型的异常链链接起来,应该使用initCause()方法而不是构造器。
1 package 异常.Finally; 2 3 import java.io.EOFException; 4 import java.io.IOException; 5 6 public class ReThrow { 7 8 public static void main(String[] args) { 9 try { 10 exp(); 11 } catch (Exception e) { 12 e.printStackTrace(); 13 } 14 } 15 16 public static void test() throws Exception { 17 try { 18 throw new EOFException(); 19 }catch(Exception e) { 20 //将原始的EOFException保存下来,抛出另一个异常IOException 21 IOException io = new IOException("IO异常"); 22 io.initCause(e); 23 throw io; 24 } 25 } 26 27 public static void exp() throws Exception { 28 try { 29 test(); 30 }catch(Exception e) { 31 //对于Exception可以直接在构造器中指定原始异常 32 Exception ex = new Exception(e); 33 throw ex; 34 } 35 } 36 37 }
控制台:
java.lang.Exception: java.io.IOException: IO异常 at 异常.Finally.ReThrow.exp(ReThrow.java:31) at 异常.Finally.ReThrow.main(ReThrow.java:10) Caused by: java.io.IOException: IO异常 at 异常.Finally.ReThrow.test(ReThrow.java:21) at 异常.Finally.ReThrow.exp(ReThrow.java:29) ... 1 more Caused by: java.io.EOFException at 异常.Finally.ReThrow.test(ReThrow.java:18) ... 2 more