1. 概要

Java Reflection API を使用する場合、 java.lang.reflect.InvocationTargetExceptionが発生するのが一般的です。

このチュートリアルでは、簡単な例でそれとその処理方法を見ていきます。 。 

2. InvocationTargetExceptionの原因

これは主に、リフレクションレイヤーを操作して、基になる例外自体をスローするメソッドまたはコンストラクターを呼び出そうとしたときに発生します。

リフレクションレイヤーは、メソッドによってスローされた実際の例外をInvocationTargetExceptionでラップします。

例を挙げて理解してみましょう。

意図的に例外をスローするメソッドを使用してクラスを作成します。

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

SimpleJUnit5テストでリフレクションを使用して上記のメソッドを呼び出しましょう。

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

上記のコードでは、メソッドの呼び出し中にスローされるInvocationTargetExceptionをアサートしました。 ここで注意すべき重要な点は、実際の例外(この場合は ArithmeticException )がInvocationTargetExceptionにラップされることです。

さて、そもそもリフレクションが実際の例外をスローしないのはなぜですか?

その理由は、 Exception が反射層を介したメソッドの呼び出しに失敗したために発生したのか、それともメソッド自体の中で発生したのかを理解できるためです。

3. InvocationTargetException を処理する方法は?

ここで、実際の根本的な例外は InvocationTargetException の原因であるため、 Throwable.getCause()を使用して詳細情報を取得できます。

getCause()を使用して、上記で使用したのと同じ例で実際の例外を取得する方法を見てみましょう。

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

スローされたのと同じexceptionオブジェクトでgetCause()メソッドを使用しました。 そして、例外の原因としてArithmeticException.classを主張しました。

したがって、基になる例外を取得したら、同じものを再スローするか、カスタム例外でラップするか、要件に基づいて例外をログに記録することができます。

4. 結論

この短い記事では、反射レイヤーが根本的な例外をどのようにラップするかを見ました。

また、 InvocationTargetException の根本的な原因を特定する方法と、そのようなシナリオを簡単な例で処理する方法についても説明しました。

いつものように、この記事で使用されているコードは、GitHubから入手できます。