Java 逆引き集 | リフレクション基礎(Class, Method) — フレームワーク開発/DI

Java Java
スポンサーリンク

リフレクション基礎(Class, Method) — フレームワーク開発/DI

Javaの リフレクション(Reflection) は「クラスやメソッドを動的に調べたり呼び出したりする仕組み」です。
通常は newobj.method() のように静的に書きますが、リフレクションを使うと「文字列で指定されたクラスをロード」「メソッド名で呼び出し」などが可能になります。フレームワーク開発やDI(依存性注入)でよく使われます。


基本概念

  • Classオブジェクト: クラスのメタ情報を保持。Class<?> 型。
  • Methodオブジェクト: メソッドのメタ情報を保持。java.lang.reflect.Method
  • 用途:
    • 設定ファイルやアノテーションからクラスを動的にロード。
    • メソッド名を文字列で指定して呼び出す。
    • フレームワークがユーザークラスを自動的に操作する。

Class の取得方法

// 1. クラスリテラル
Class<?> c1 = String.class;

// 2. インスタンスから
String s = "abc";
Class<?> c2 = s.getClass();

// 3. 名前から動的ロード
Class<?> c3 = Class.forName("java.util.ArrayList");
Java

👉 フレームワークは「名前からロード」を多用。


Method の取得と呼び出し

import java.lang.reflect.*;

class User {
    public void hello(String msg) {
        System.out.println("Hello " + msg);
    }
}

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("User");
        Object obj = clazz.getDeclaredConstructor().newInstance();

        Method m = clazz.getMethod("hello", String.class);
        m.invoke(obj, "Tanaka"); // Hello Tanaka
    }
}
Java
  • getMethod: 公開メソッドを取得。引数型を指定。
  • invoke: 実際に呼び出す。第一引数は対象オブジェクト、第二以降は引数。
  • 例外: ClassNotFoundException, NoSuchMethodException, InvocationTargetException などに注意。

例題で練習

例題1: クラス名からインスタンス生成

String className = "java.util.HashMap";
Class<?> clazz = Class.forName(className);
Object obj = clazz.getDeclaredConstructor().newInstance();
System.out.println(obj.getClass().getName()); // java.util.HashMap
Java

👉 設定ファイルで指定されたクラスをロードするイメージ。


例題2: メソッド呼び出し(DI風)

class Service {
    public void run() { System.out.println("サービス実行"); }
}

String className = "Service";
Class<?> clazz = Class.forName(className);
Object obj = clazz.getDeclaredConstructor().newInstance();

Method m = clazz.getMethod("run");
m.invoke(obj); // サービス実行
Java

👉 DIコンテナが「サービスクラス」を自動生成して呼び出すイメージ。


例題3: フィールドアクセス

class Config {
    public String url = "http://example.com";
}

Class<?> clazz = Config.class;
Object obj = clazz.getDeclaredConstructor().newInstance();

Field f = clazz.getField("url");
System.out.println(f.get(obj)); // http://example.com
Java

👉 設定値を動的に読み取る。


テンプレート集

クラスロード

Class<?> clazz = Class.forName("パッケージ.クラス名");
Object obj = clazz.getDeclaredConstructor().newInstance();
Java

メソッド呼び出し

Method m = clazz.getMethod("メソッド名", 引数型...);
Object result = m.invoke(obj, 引数...);
Java

フィールドアクセス

Field f = clazz.getField("フィールド名");
Object value = f.get(obj);
f.set(obj, 新しい値);
Java

実務での注意点

  • パフォーマンス: リフレクションは遅い。大量呼び出しには不向き。
  • 型安全性: コンパイル時チェックが効かない。間違えると実行時例外。
  • セキュリティ: private フィールドやメソッドにもアクセスできるが、制約やセキュリティマネージャに注意。
  • 用途限定: フレームワークやツール開発で便利だが、通常業務コードでは避けるのが無難。

まとめ

  • Class / Method / Field を使うと「動的にクラスやメソッドを操作」できる。
  • フレームワーク開発やDIで必須の技術。
  • 型安全性やパフォーマンスに注意しつつ、設定駆動の柔軟な設計が可能。

👉 練習課題として「クラス名を文字列で受け取り、そのクラスの toString() を呼び出す」コードを書いてみると、リフレクションの基本が体感できます。

タイトルとURLをコピーしました