getCause()方法

来源:互联网 发布:netstat 显示端口号 编辑:程序博客网 时间:2024/06/10 08:55

一、
下图节选自《Java编程思想》第四版,图中这个程序的大意是,定义了一个方法能抛出3种异常,且把这几个异常捕获后包装进RuntimeException对象再抛出;在main()里调用上述方法并捕获到它抛出的RuntimeException异常后,用getCause()方法把被包装的原始异常提取出来,再用它们自己的catch子句进行处理。

这里写图片描述
这里写图片描述

二、
参照上述示例的流程自己写一个程序尝试一下:自定义一个异常类E1,定义f()方法抛出E1并包装进RuntimeException对象,在main()里调用f()并捕获该RuntimeException异常,再用getCause()方法提取出被包装的E1,最后捕获并打印出该E1异常:

class E1 extends Exception{}public class Test1{    static void f(){        try{            throw new E1();    //抛出E1        }catch(E1 e){            throw new RuntimeException(e);   //把E1包装进RuntimeException,E1成了它的cause        }    }    public static void main(String[] args){        try{            f();        }catch(RuntimeException e1){    //捕获f()抛出的包装了E1的RuntimeException            try{                throw e1.getCause();   //提取该RuntimeException的cause,E1            }catch(E1 e2){             //捕获提取出的E1                e2.printStackTrace();            }        }    }}

运行结果:

C:\Users\Administrator\java\chp12>javac Test1.javaTest1.java:16: 错误: 未报告的异常错误Throwable; 必须对其进行捕获或声明以便抛出                                throw e1.getCause();                                ^1 个错误

结果报了1个错误,按照报错信息,是提取出来的E1没有被捕获或者做异常声明;但是程序17行明明有写catch(E1 e2)来捕获提取出的原始异常,而且上图书上为什么是可行的。

三、
getCause()的官方API定义如下:返回异常的原因
public Throwable getCause()
Returns the cause of this exception (the Throwable instance wrapped in this UndeclaredThrowableException, which may be null).

猜测:书上的原始异常IOException和FileNotFoundException是系统已定义的异常,提取之后系统能识别,而我上述代码的异常E1是自定义的异常。为验证猜想,将上述E1替换成IOException,结果仍然报上述错误,所以猜测不成立。

那么就按照错误提示加上异常声明如下,结果仍报上述错误:

public static void main(String[] args) throws E1{

综上即便是有捕获E1异常或者声明抛出E1异常,都仍会报错说没有捕获或报告。由此推断,程序在编译的时候,并不能知道getCause()提取出的异常会是哪种具体异常类型。

那么解决方法就是加一行捕获父类Throwable的代码(或者异常声明抛出Throwable也是一样的效果),以使编译通过。由以下程序的输出结果可知,程序实际运行时还是走的catch(E1 e2){…}而不是catch(Throwable){}。回过头看书上最后也是有捕获Throwable以使编译通过:

class E1 extends Exception{}public class Test1{    static void f(){        try{            throw new E1();        }catch(E1 e){            throw new RuntimeException(e);        }    }    public static void main(String[] args) throws E1{        try{            f();        }catch(RuntimeException e1){            try{                throw e1.getCause();            }catch(E1 e2){             //实际运行的捕获语句                e2.printStackTrace();              }catch(Throwable e3){}    //加上这一行,即可编译通过        }    }}

运行结果:

E1        at Test1.f(Test1.java:6)        at Test1.main(Test1.java:13)