リフレクションとは、プログラムの実行中にクラス、オブジェクト、メソッド、およびフィールドの構造と動作を調査および変更することを可能にするメカニズムです。これはjava.lang.reflectパッケージを通じて実装されます。
できること:
例:
import java.lang.reflect.Method; public class ReflectionExample { public void greet() { System.out.println("Hello!"); } public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("ReflectionExample"); Object instance = clazz.getDeclaredConstructor().newInstance(); Method method = clazz.getMethod("greet"); method.invoke(instance); // 出力: Hello! } }
利点:
欠点/リスク:
リフレクションを使用してクラスのプライベートフィールドやメソッドにアクセスできるか、結果はどうなりますか?
回答: はい、FieldまたはMethodのsetAccessible(true)メソッドを使用することで可能です:
Field field = clazz.getDeclaredField("privateField"); field.setAccessible(true); field.set(obj, "value");
これはクラスのカプセル化を破壊し、リスクを伴います:状況が脆弱になり、セキュリティ上のエラーが発生する可能性があり、新しいバージョンのJVMではこれらの行動がアクセスポリシーによって制限されることがあります。
ストーリー
大規模なプロジェクトでリフレクションを介した自動マッピングDTOのフィールドが「Optional」型で正しく考慮されず、データの大量処理時にNullPointerExceptionが発生しました。なぜなら、リフレクションパッケージがOptional値とnullを区別しなかったからです。
ストーリー
銀行ソフトウェアでプライベートフィールドへのアクセスがsetAccessible(true)を介してシリアル化のために実装されました。JVMの更新後、動作が変更され、プライベートフィールドへのアクセスが制限され、重要なシリアル化機能が突然プロダクションで動作しなくなりました。
ストーリー
ORMフレームワークでプロキシオブジェクトを生成する際に、データスキーマの変更後にリフレクションのキャッシュを更新するのを忘れました。その結果、新しいクラスのフィールドで予測できない例外が発生しましたが、キャッシュには反映されていませんでした。