«1. Обзор

При работе с Java Reflection API часто возникает исключение java.lang.reflect.InvocationTargetException. В этом уроке мы рассмотрим это и как с этим справиться на простом примере.

2. Причина InvocationTargetException

В основном это происходит, когда мы работаем со слоем отражения и пытаемся вызвать метод или конструктор, который сам генерирует базовое исключение.

Слой отражения оборачивает фактическое исключение, созданное методом, с помощью InvocationTargetException. Попробуем понять это на примере.

Давайте напишем класс с методом, который намеренно генерирует исключение:

public class InvocationTargetExample {
    public int divideByZeroExample() {
        return 1 / 0;
    }
}

Теперь давайте вызовем вышеуказанный метод, используя отражение в простом тесте JUnit 5:

InvocationTargetExample targetExample = new InvocationTargetExample(); 
Method method =
  InvocationTargetExample.class.getMethod("divideByZeroExample");
 
Exception exception =
  assertThrows(InvocationTargetException.class, () -> method.invoke(targetExample));

В приведенном выше примере кода мы установили исключение InvocationTargetException, которое генерируется при вызове метода. Здесь важно отметить, что фактическое исключение — в данном случае ArithmeticException — оборачивается в InvocationTargetException.

Теперь вопрос, который приходит на ум, заключается в том, почему отражение не выдает фактическое исключение в первую очередь?

Причина в том, что это позволяет нам понять, возникло ли Исключение из-за сбоя при вызове метода через слой отражения или оно произошло внутри самого метода.

3. Как обрабатывать исключение InvocationTargetException?

Здесь фактическое базовое исключение является причиной InvocationTargetException, поэтому мы можем использовать Throwable.getCause(), чтобы получить больше информации об этом.

Давайте посмотрим, как мы можем использовать getCause() для получения фактического исключения в том же примере, что и выше:

assertEquals(ArithmeticException.class, exception.getCause().getClass());

Здесь мы использовали метод getCause() для того же объекта исключения, который был сгенерирован. И мы заявили ArithmeticException.class как причину исключения.

Итак, как только мы получим базовое исключение, мы можем повторно сгенерировать его, обернуть его в какое-то пользовательское исключение или просто зарегистрировать исключение в соответствии с нашим требованием.

4. Заключение

В этой короткой статье мы увидели, как слой отражения оборачивает любое базовое исключение. Мы также увидели, как определить основную причину InvocationTargetException и как справиться с таким сценарием на простом примере.

Как обычно, код, использованный в этой статье, доступен на GitHub.