在做单元测试时候,在一个私有方法中抛出了自定义异常。使用method.invoke()
之后,使用try{} catch (自定义异常){}
进行捕获,竟然没有捕获到,最终定位到原因是:如果方法中直接抛出异常,通过反射进行调用时,会抛出InvocationTargetException异常
public class MyException extends RuntimeException {
String msg;
MyException() {
super();
}
MyException(String msg) {
super(msg);
this.msg = msg;
}
}
public class Test {
public static void main(String[] args) throws Exception {
Test t = new Test();
Class clz = t.getClass();
Method addMethod = clz.getDeclaredMethod("divde", int.class, int.class);
System.out.println(addMethod.invoke(new Test(), 1, 0));
}
private double divde(int x, int y) {
if (y == 0) {
throw new MyException("除数不能为0");
}
return 1.0 * x / y;
}
}
Exception in thread "main" 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 Test.main(Test.java:29)
Caused by: MyException: 除数不能为0
at Test.divde(Test.java:45)
... 5 more
通过异常日志我们可以看出来其实最终抛出的是java.lang.reflect.InvocationTargetException
异常。通过源码注释我们也可以得出该结论。
/**
* @exception InvocationTargetException if the underlying method throws an exception.
*/
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
通过caused by可以看出该异常是由于自定义异常导致的。我们可以通过ex.getTargetException()
获取目标异常。代码以及对应的日志如下:
public class Test {
public static void main(String[] args) throws Exception {
Test t = new Test();
Class clz = t.getClass();
Method addMethod = clz.getDeclaredMethod("divde", int.class, int.class);
try {
System.out.println(addMethod.invoke(new Test(), 1, 0));
} catch (InvocationTargetException ex) {
System.out.println("以下是InvocationTargetException异常:");
ex.printStackTrace();
System.out.println("以下是目标异常:");
ex.getTargetException().printStackTrace();
}
}
private double divde(int x, int y) {
if (y == 0) {
throw new MyException("除数不能为0");
}
return 1.0 * x / y;
}
}
以下是InvocationTargetException异常:
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 Test.main(Test.java:31)
Caused by: MyException: 除数不能为0
at Test.divde(Test.java:46)
... 5 more
以下是目标异常:
MyException: 除数不能为0
at Test.divde(Test.java:46)
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 Test.main(Test.java:31)