リフレクション基礎(Class, Method) — フレームワーク開発/DI
Javaの リフレクション(Reflection) は「クラスやメソッドを動的に調べたり呼び出したりする仕組み」です。
通常は new や obj.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() を呼び出す」コードを書いてみると、リフレクションの基本が体感できます。
