1. Overview
1.概述
When working with Java Reflection API, it is common to encounter java.lang.reflect.InvocationTargetException.
在使用Java Reflection API时,经常会遇到java.lang.reflect.InvocationTargetException。
In this tutorial, we’ll take a look at it and how to handle it with a simple example.
在本教程中,我们将通过一个简单的例子来看看它以及如何处理它。
2. Cause of InvocationTargetException
2.InvocationTargetException的原因
It mainly occurs when we work with the reflection layer and try to invoke a method or constructor that throws an underlying exception itself.
它主要发生在我们使用反射层,并试图调用一个本身抛出底层异常的方法或构造函数。
The reflection layer wraps the actual exception thrown by the method with the InvocationTargetException.
反射层用InvocationTargetException来包装方法所抛出的实际异常。
Let’s try to understand it with an example.
让我们试着用一个例子来理解它。
We’ll write a class with a method that intentionally throws an exception:
我们将编写一个带有故意抛出异常的方法的类。
public class InvocationTargetExample {
public int divideByZeroExample() {
return 1 / 0;
}
}
Let’s invoke the above method using reflection in a Simple JUnit 5 Test:
让我们在一个简单的JUnit 5测试中使用反射来调用上述方法。
InvocationTargetExample targetExample = new InvocationTargetExample();
Method method =
InvocationTargetExample.class.getMethod("divideByZeroExample");
Exception exception =
assertThrows(InvocationTargetException.class, () -> method.invoke(targetExample));
In the above code, we have asserted the InvocationTargetException, which is thrown while invoking the method. An important thing to note here is that the actual exception — ArithmeticException in this case — gets wrapped into an InvocationTargetException.
在上面的代码中,我们已经断言了InvocationTargetException,它是在调用方法时抛出的。这里需要注意的是,实际的异常–本例中的ArithmeticException–被包装成InvocationTargetException。
Now, why doesn’t reflection throw the actual exception in the first place?
现在,为什么反射不首先抛出实际的异常?
The reason is that it allows us to understand whether the Exception occurred due to failure in calling the method through the reflection layer or whether it occurred within the method itself.
原因是它允许我们了解Exception的发生是由于通过反射层调用方法的失败还是发生在方法本身。
3. How to Handle InvocationTargetException?
3.如何处理InvocationTargetException?
Here the actual underlying exception is the cause of InvocationTargetException, so we can use Throwable.getCause() to get more information about it.
这里实际的底层异常是InvocationTargetException的原因,所以我们可以使用Throwable.getCause()来获得更多相关信息。
Let’s see how we can use getCause() to get the actual exception in the same example used above:
让我们看看我们如何使用 getCause()来获得上面使用的同一个例子中的实际异常。
assertEquals(ArithmeticException.class, exception.getCause().getClass());
We’ve used the getCause() method on the same exception object that was thrown. And we have asserted ArithmeticException.class as the cause of the exception.
我们在被抛出的同一个exception对象上使用了getCause()方法。我们断言ArithmeticException.class是导致该异常的原因。
So, once we get the underlying exception, we can re-throw the same, wrap it in some custom exception or simply log the exception based on our requirement.
因此,一旦我们得到了底层的异常,我们可以重新抛出相同的异常,将其包裹在一些自定义的异常中,或者根据我们的要求简单地记录该异常。
4. Conclusion
4.总结
In this short article, we saw how the reflection layer wraps any underlying exception.
在这篇短文中,我们看到了反射层是如何包装任何底层异常的。
We also saw how to determine the underlying cause of the InvocationTargetException and how to handle such a scenario with a simple example.
我们还看到了如何确定InvocationTargetException的根本原因,以及如何通过一个简单的例子来处理这种情况。
As usual, the code used in this article is available over on GitHub.
像往常一样,本文中使用的代码可在GitHub上获得,。