メソッドの呼び出しとフィールドへのアクセス
Method.invoke と Field.set を setAccessible と組み合わせ、private メソッドを呼び出してアクセスできないフィールドを設定します。
「メソッドの呼び出しとフィールドへのアクセス」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
setAccessible:可視性の回避
field.setAccessible(true)または method.setAccessible(true)を呼び出すと、Java のアクセス制御を回避できます。private メンバーにアクセスするために必要です。Java 9 以降では、適切なモジュールアクセスも必要です。
Field f = User.class.getDeclaredField("name");
f.setAccessible(true);
User u = new User("Alice", 30);
System.out.println(f.get(u)); // "Alice"
f.set(u, "Bob"); // mutate the private field
System.out.println(u.getName()); // "Bob"フィールド値の読み取り
field.get(instance)を使用すると、任意のフィールド値を読み取れます(プリミティブ型はボックス化されます)。static フィールドの場合は、インスタンスとして nullを渡します。
Field f = MyClass.class.getDeclaredField("count");
f.setAccessible(true);
int count = (int) f.get(null); // static field → null instanceフィールド値の設定
field.set(instance, value)を使用してフィールドに値を書き込みます。値の型は一致しているか、自動アンボックス化できる必要があります。現代の JVM でリフレクションにより finalフィールドを設定した場合の動作は未定義です。
Field nameField = User.class.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(user, "Charlie");リフレクションによるメソッド呼び出し
Methodオブジェクトを取得し、setAccessible(true)を呼び出してから、method.invoke(instance, args...)で呼び出します。戻り値の型は Objectです。
Method greet = User.class.getDeclaredMethod("greet", String.class);
greet.setAccessible(true);
String result = (String) greet.invoke(user, "World");
System.out.println(result);InvocationTargetException の処理
呼び出したメソッドが例外をスローすると、リフレクションによって InvocationTargetExceptionにラップされます。getCause()で元の例外を取り出します。
try {
method.invoke(obj, args);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
System.err.println("Method threw: " + cause.getMessage());
} catch (IllegalAccessException | NoSuchMethodException e) {
System.err.println("Reflection error: " + e.getMessage());
}static メソッドの呼び出し
static メソッドを呼び出す場合は、インスタンス引数として nullを渡します。
Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class);
int value = (int) parseInt.invoke(null, "42"); // null = static
System.out.println(value); // 42コンストラクターによるインスタンスの生成
Constructorを取得し、private コンストラクターの場合は setAccessible(true)を呼び出してから、newInstance(args...)を実行します。
Constructor<User> ctor = User.class.getDeclaredConstructor(String.class, int.class);
ctor.setAccessible(true);
User u = ctor.newInstance("Diana", 28);
System.out.println(u);フレームワークでのリフレクション:Spring DI
Spring はリフレクションを使用して Bean をインスタンス化し、依存関係を注入します。private コンストラクターを呼び出し、private フィールドを設定してアプリケーションコンテキストを構成します。
Java 9 以降のモジュールアクセス
Java 9 以降では、モジュールによって setAccessibleがデフォルトで制限されます。クラスが名前付きモジュールにある場合は、パッケージを open にする必要があります。--add-opens java.base/java.lang=ALL-UNNAMEDを使用します。
// JVM flag to open a package for reflection:
// --add-opens java.base/java.lang=ALL-UNNAMED高速な代替手段としての MethodHandles
MethodHandles.lookup().findVirtual()はリフレクションによるメソッド呼び出しを提供し、JIT 最適化後は直接呼び出しに近い性能を実現します。パフォーマンスが重要なライブラリコードで推奨されます。
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(User.class, MethodHandles.lookup());
MethodHandle handle = lookup.findVirtual(User.class, "getName", MethodType.methodType(String.class));
String name = (String) handle.invoke(user);リフレクションのベストプラクティス
Field/Methodオブジェクトをキャッシュし、ホットループ内で取得しないでください。リフレクションはサービスクラスでラップします。パフォーマンスが必要な場合は MethodHandles を検討します。可能な場合はリフレクションよりインターフェースを優先します。
理解度チェック
リフレクションで呼び出したメソッドが例外をスローした場合、その原因をラップする例外は何ですか?
まとめ
setAccessible(true)を使用して private メンバーにアクセスします。method.invoke()でメソッドを呼び出します。InvocationTargetExceptionから元の例外を取り出します。リフレクションで扱うオブジェクトをキャッシュし、ホットパスでは MethodHandles を優先します。
よくある質問
「メソッドの呼び出しとフィールドへのアクセス」レッスンは無料ですか?
はい。「メソッドの呼び出しとフィールドへのアクセス」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「メソッドの呼び出しとフィールドへのアクセス」で何を学びますか?
Method.invoke と Field.set を setAccessible と組み合わせ、private メソッドを呼び出してアクセスできないフィールドを設定します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「メソッドの呼び出しとフィールドへのアクセス」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- リフレクションによるクラスの調査
- メソッドの呼び出しとフィールドへのアクセス
- InvocationHandler による動的プロキシ
- リフレクションの性能と代替手段