1. 前言
在我们使用Java的反射API时,我们经常会遇到java.lang.reflect.InvocationTargetException异常,在本教程中,我们将通过一个简单的实例来了解它以及处理它。
2. 引发InvocationTargetException异常的原因
在我们使用反射API去调用一个方法或者构造函数时,此时如果被调用的方法或者构造函数抛出异常,反射API则会使用InvocationTargetException异常类来包裹住真正的异常。
下面我们来演示一下如何引发该异常,首先我们编写一个能够抛出异常的类(下面的代码抛出ArithmeticException异常):
public class InvocationTargetExample {
public int divideByZeroExample() {
return 1 / 0;
}
}
现在,我们在一个JUnit5单元测试中使用反射API来调用上面这个方法:
InvocationTargetExample targetExample = new InvocationTargetExample();
// 使用反射API调用divideByZeroExample方法。
Method method =
InvocationTargetExample.class.getMethod("divideByZeroExample");
// 断言成功
Exception exception =
assertThrows(InvocationTargetException.class, () -> method.invoke(targetExample));
在上面的代码中,我们使用一个断言来检测InvocationTargetException异常,该断言可以成功执行。由此可以判断:虽然divideByZeroExample方法抛出的异常是ArithmeticException,但是通过反射API调用抛出的异常却变为了InvocationTargetException。现在,我们可能会产生疑问,为什么反射API不直接抛出真正的异常?
反射API这样设计的目的是为了让程序员能够区分异常是反射API自身抛出的,还是被调用的方法中抛出。
3. 如何处理InvocationTargetException 异常?
由上可知,InvocationTargetException异常只是包装了被调用方法所抛出的异常,我们可以使用Throwable.getCause()方法来获取到真正的异常。
我们继续上面的例子:
assertEquals(ArithmeticException.class, exception.getCause().getClass());
这里,我们已经知道被调用的方法会抛出ArithmeticException异常,所以上面的断言可以通过。
所以,我们可以在获取到真正的异常后进一步的处理它,例如,重新抛出真正的异常。
4. 总结
在这片文章中,我们了解到反射API是如何处理异常的,我们还学会了如何确定引发InvocationTargetException异常的真正原因。