Java异常处理之java.lang.reflect.InvocationTargetException

作者 | 2020年4月21日

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异常的真正原因。

发表评论

电子邮件地址不会被公开。 必填项已用*标注