在设计模式中有一个叫做责任链模式,该模式是将多个对象链接成一条链,客户端的请求沿着这条链传递直到被接收、处理。同样 Java 异常机制也提供了这样一条链:异常链。
我们知道每遇到一个异常信息,我们都需要进行 try…catch,一个还好,如果出现多个异常呢?分类处理肯定会比较麻烦,那就一个 Exception 解决所有的异常吧。这样确实是可以,但是这样处理势必会导致后面的维护难度增加。最好的办法就是将这些异常信息封装,然后捕获我们的封装类即可。
诚然在应用程序中,我们有时候不仅仅只需要封装异常,更需要传递。怎么传递?throws!!但是如果仅仅只用 throws 抛出异常,那么你的封装类,怎么办??
我们有两种方式处理异常,一是 throws 抛出交给上级处理,二是 try…catch 做具体处理。但是这个与上面有什么关联呢?try…catch 的 catch 块我们可以不需要做任何处理,仅仅只用 throw 这个关键字将我们封装异常信息主动抛出来。然后在通过关键字 throws 继续抛出该方法异常。它的上层也可以做这样的处理,以此类推就会产生一条由异常构成的异常链。
通过使用异常链,我们可以提高代码的可理解性、系统的可维护性和友好性。
同理,我们有时候在捕获一个异常后抛出另一个异常信息,并且希望将原始的异常信息也保持起来,这个时候也需要使用异常链。
在异常链的使用中,throw 抛出的是一个新的异常信息,这样势必会导致原有的异常信息丢失,如何保持?在 Throwable 及其子类中的构造器中都可以接受一个 cause 参数,该参数保存了原有的异常信息,通过 getCause ()就可以获取该原始异常信息。
import java.io.FileNotFoundException; import java.io.FileReader; import java.util.Scanner; class MyException extends Exception { public MyException(String message) { super(message); } public MyException(String message, Exception e) { super(message, e); } } public class Test { public void f() throws MyException { try { FileReader reader = new FileReader("G:\myfile\struts.txt"); Scanner in = new Scanner(reader); System.out.println(in.next()); } catch (FileNotFoundException e) { //e 保存异常信息 throw new MyException("文件没有找到--01", e); } } public void g() throws MyException { try { f(); } catch (MyException e) { //e 保存异常信息 throw new MyException("文件没有找到--02", e); } } public static void main(String[] args) { Test t = new Test(); try { t.g(); } catch (MyException e) { e.printStackTrace(); } } }
运行结果:
utils.MyException: 文件没有找到--02 at utils.Test.g(Test.java:35) at utils.Test.main(Test.java:42) Caused by: utils.MyException: 文件没有找到--01 at utils.Test.f(Test.java:26) at utils.Test.g(Test.java:32) ... 1 more Caused by: java.io.FileNotFoundException: G:myfilestruts.txt (系统找不到指定的路径。) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.<init>(FileInputStream.java:138) at java.io.FileInputStream.<init>(FileInputStream.java:93) at java.io.FileReader.<init>(FileReader.java:58) at utils.Test.f(Test.java:21) ... 2 more Process finished with exit code 0