问题描述
反射调用方法时,方法内部抛出了自定义异常,但是无法在反射调用的时候捕获到抛出的自定义异常。
代码如下:
// 自定义异常
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
是用来处理内部方法抛出异常的
继续看InvocationTargetException
的说明
InvocationTargetException
是一个受检查的异常,包含了由调用方法或构造函数引发的异常
InvocationTargetException
有两个方法可以获取方法内部抛出的异常
因此修改捕获的方法
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:自定义异常
可以看到方式一和方式二是一样的,那么getTargetException
和getCause
有什么区别呢
再次看到文档,这里指出getCause()
是首选的方法,因此使用方式二就行了
网友评论