Java反射调用方法时捕获异常

问题描述

反射调用方法时,方法内部抛出了自定义异常,但是无法在反射调用的时候捕获到抛出的自定义异常。
代码如下:

// 自定义异常
public class MyException extends Exception {
    private static final long serialVersionUID = -7998753885990231365L;
    private String code;
    public MyException(String code, String message) {
        super(message);
                this.code = code;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}
// 反射调用的方法
public class MethodThrowMyException {
    public String throwMyException() throws MyException {
        throw new MyException("1", "自定义异常");
    }
}
// 捕获异常
public class Invocation {
    public static void main(String[] args) {
        try {
            Class<?> c = Class.forName("myexception.MethodThrowMyException");
            Object o = c.newInstance();
            Method m = c.getMethod("throwMyException");
            m.invoke(o);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch(MyException e) {
            
        }
    }
}
这里会报错,Unreachable catch block for MyException. This exception is never thrown from the try statement body

问题解决

参考文章
可以发现,JDK的API文档中,关于method.invoke的注释说明
InvocationTargetException是用来处理内部方法抛出异常的

图1

继续看InvocationTargetException说明
InvocationTargetException是一个受检查的异常,包含了由调用方法或构造函数引发的异常

图2

InvocationTargetException有两个方法可以获取方法内部抛出的异常

图3

因此修改捕获的方法
public class Invocation {
    public static void main(String[] args) {
        try {
            Class<?> c = Class.forName("myexception.MethodThrowMyException");
            Object o = c.newInstance();
            Method m = c.getMethod("throwMyException");
            m.invoke(o);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

            // 方式一
            Throwable targetException = e.getTargetException();
            if(targetException instanceof MyException) {
                System.out.println("捕获到自定义异常");
                System.out.println("code:" + ((MyException) targetException).getCode());
                System.out.println("message:" + targetException.getMessage());
            }

            // 方式二
            Throwable cause = e.getCause();
            if (cause instanceof MyException) {
                System.out.println("捕获到自定义异常");
                System.out.println("code:" + ((MyException) cause).getCode());
                System.out.println("message:" + cause.getMessage());
            }
        }
    }
}

得到结果:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at myexception.Invocation.main(Invocation.java:12)
Caused by: myexception.MyException: 自定义异常
    at myexception.MethodThrowMyException.throwMyException(MethodThrowMyException.java:5)
    ... 5 more
捕获到自定义异常
code:1
message:自定义异常
可以看到方式一和方式二是一样的,那么getTargetExceptiongetCause有什么区别呢

再次看到文档,这里指出getCause()是首选的方法,因此使用方式二就行了

图4
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容