リフレクションとメソッド/変数ハンドルは、開発者が実行時にオブジェクトにアクセスして操作できるようにする Java の 2 つの強力な機能です。ただし、オブジェクトにアクセスして処理する方法が異なります。
リフレクションを使用してクラス内のメソッドにアクセスする方法の例を見てみましょう。まず、プライベート文字列変数とその変数のゲッター メソッドを持つ「MyClass」という単純なクラスから始めます。このオブジェクトを作成するには、通常のインスタンス化を使用できます:
MyClass objectInstance = new MyClass("John Doe");
リフレクションを使用してメソッドにアクセスするには、まず getClass() メソッドを使用してオブジェクト インスタンスのクラスを取得する必要があります。次に、getDeclaredMethod() メソッドを使用して、アクセスしたいメソッド (この場合は「getName」) を見つけます。最後に、invoke() メソッドを使用してメソッドを呼び出し、オブジェクト インスタンスを渡す必要があります。このプロセスのコードは次のとおりです:
Class<?> clazz = objectInstance.getClass(); Method method = clazz.getDeclaredMethod("getName"); String value = (String) method.invoke(objectInstance); System.out.println(value); // prints "John Doe"
一方、MethodHandles クラスにあるメソッド ハンドルは、メソッドにアクセスするためのより安全で最適化された方法を提供します。これは、これらがこの目的のために特別に設計されており、JVM 最適化のために強化されているためです。
メソッド ハンドルを使用してメソッドにアクセスすることは、リフレクションを使用することと似ています。まず、オブジェクト インスタンスのクラスを取得します。次に、MethodHandles の findVirtual() メソッドを使用して、アクセスするメソッドを検索します。次に、invoke() メソッドを使用してメソッドを呼び出し、オブジェクト インスタンスを渡します。このプロセスのコードは次のとおりです:
Class<?> clazz = objectInstance.getClass(); MethodHandle handle = MethodHandles.lookup().findVirtual(clazz, "getName", methodType(String.class)); String value = (String) handle.invoke(objectInstance); System.out.println(value); // Prints “John Doe”
ただし、メソッド ハンドルでできることには制限があります。クラスのインスタンス化などのタスクは処理できませんが、リフレクションでは可能です。
メソッド ハンドルの威力を示すために、メソッド ハンドルを使用してクラス内のプライベート フィールドに直接アクセスする方法を見てみましょう。 「MyClass」クラスに「name」というプライベート文字列変数があるとします。リフレクションを使用してアクセスすることもできますが、メソッド ハンドルを使用する方が安全です。
リフレクションを使用してプライベート フィールドに直接アクセスするには、まずオブジェクト インスタンスのクラスを取得する必要があります。次に、getDeclaredField() メソッドを使用して、アクセスするフィールド (この場合は「name」) を見つけます。ただし、このフィールドはプライベートであるため、setAccessible() メソッドを使用してそのアクセシビリティを true に設定する必要があります。最後に、get() メソッドを使用してフィールドの値を取得できます。このプロセスのコードは次のとおりです:
Class<?> clazz = objectInstance.getClass(); Field field = clazz.getDeclaredField("name"); field.setAccessible(true); String value = (String) field.get(objectInstance); System.out.println(value); // prints “John Doe”
メソッド ハンドルを使用する場合も、プロセスは同様です。まずオブジェクト インスタンスのクラスを取得し、次に MethodHandles の privateLookupIn() メソッドを使用して、フィールドのアクセス修飾子を尊重します (プライベートであるため)。次に、findVarHandle() メソッドを使用して、アクセスするフィールドを見つけます。最後に、get() メソッドを使用してその値を取得できます。このプロセスのコードは次のとおりです:
Class<?> clazz = objectInstance.getClass(); VarHandle handle = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup()).findVarHandle(clazz, "name", String.class); String value = (String) handle.get(objectInstance); System.out.println(value); // prints “John Doe”
パフォーマンス上の理由からハンドルを静的にインスタンス化することをお勧めしますが、これにはクラスの名前を知っている必要があります。クラスの名前がわからない場合、このアプローチを使用することはできません。
メソッド ハンドルの制限の 1 つは、チェックされた例外を処理する方法が提供されていないことです。メソッド ハンドルと var ハンドルに対するさまざまな操作は、実稼働コードでキャッチして宣言する必要があるチェック例外をスローします。
結論として、メソッドと変数のハンドルは、クラスのメタデータを検索し、通常の Java 制限の外でメソッドとフィールドにアクセスするための、JDK の集中的な範囲の機能を提供します。これらはリフレクションのすべての機能をカバーしているわけではありませんが、これらのタスクに対してより安全で最適化された代替手段を提供します。
MyExamCloud の学習プランで Java 認定資格を勉強する最適な方法を体験し、無料の模擬テストをお楽しみください。
以上がJava でのメソッドおよび変数ハンドルを使用したランタイム オブジェクトのアクセスと操作の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。