Java リフレクション メカニズム (苗東百科事典)

1. 反省とは何ですか?

 リフレクションを使用すると、メンバー変数、メンバー メソッド、およびコンストラクターに関する情報にプログラムでアクセスできます。

反射はメカニズムです。どのクラスについても、このクラスのすべてのプロパティとメソッドを知ることができます。どのオブジェクトでも、このオブジェクトのすべてのプロパティとメソッドを呼び出すことができます。クラス情報を動的に取得し、オブジェクトを動的に呼び出すこの機能は、Java のリフレクション メカニズムと呼ばれます。

2. クラスオブジェクトを取得する 3 つの方法

Java では、Class オブジェクトは次の 3 つの方法で取得でき、それぞれに異なる使用シナリオがあります。

1. Class.forName() メソッドを使用します: このメソッドは、クラスの完全修飾名文字列のみがわかっている場合の使用に適しています。クラスを動的にロードして、対応する Class オブジェクトを取得できます。たとえば、一般的なコードを記述するとき、または構成ファイルでクラス名の文字列を指定するときに、このメソッドを使用して Class オブジェクトを取得できます。

try {
    Class<?> cls = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

2. .class 構文を使用する: このメソッドは、特定のクラスの型が明確にわかっている場合に適しており、クラス名とサフィックスを直接使用して、.class対応する Class オブジェクトを取得できます。たとえば、インスタンスを作成し、クラスが特定のクラスのサブクラスであるかどうかを判断する場合、このメソッドを使用して Class オブジェクトを取得できます。 

Class<?> cls = String.class;

 3. オブジェクトの getClass() メソッドを使用します。このメソッドは既存のオブジェクトに適しており、対応する Class オブジェクトを取得する必要があります。たとえば、オブジェクトの比較や型の判定、オブジェクトのメソッドの動的呼び出しを行う場合に、このメソッドを使用して Class オブジェクトを取得できます。

String str = "Hello";
Class<?> cls = str.getClass();

3. 反射取得構築法

リフレクションを使用してコンストラクターを取得するには、次の手順を実行します。

  1. Class オブジェクトを取得する: まず、ターゲット クラスの Class オブジェクトを取得する必要があります。上記の 3 つのメソッドのいずれかを使用して、Class オブジェクトを取得できます。

  2. getConstructors() または getDeclaredConstructors() メソッドを呼び出す: Class オブジェクトを通じて getConstructors() メソッドまたは getDeclaredConstructors() メソッドを呼び出して、コンストラクター配列を取得できます。これら 2 つのメソッドは、それぞれパブリック コンストラクターとすべてのコンストラクター (プライベート コンストラクターと保護されたコンストラクターを含む) を返します。

  3. コンストラクター配列を走査する: コンストラクター配列を取得した後、ループ トラバーサルを使用して各コンストラクターの詳細情報を取得できます。

  4. Constructor クラスの関連メソッドを呼び出します。コンストラクターごとに、コンストラクター名を取得する getName()、修飾子を取得する getModifiers()、修飾子を取得する getParameterTypes() など、Constructor クラスのメソッドを通じて操作できます。パラメータの型など。

以下は、リフレクションを使用してコンストラクター メソッドを取得する方法を示すサンプル コードです。

import java.lang.reflect.Constructor;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        try {
            // 步骤1:获取Class对象
            Class<?> cls = MyClass.class;
            
            // 步骤2:获取构造方法数组
            Constructor<?>[] constructors = cls.getDeclaredConstructors();
            
            // 步骤3:遍历构造方法数组
            for (Constructor<?> constructor : constructors) {
                // 步骤4:调用Constructor类的相关方法
                String name = constructor.getName();
                int modifiers = constructor.getModifiers();
                Class<?>[] parameterTypes = constructor.getParameterTypes();
                
                System.out.println("Constructor Name: " + name);
                System.out.println("Modifiers: " + modifiers);
                System.out.println("Parameter Types: " + Arrays.toString(parameterTypes));
                System.out.println();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyClass {
    public MyClass() {
    }
    
    private MyClass(int value) {
    }
}

出力結果:

Constructor Name: MyClass
Modifiers: 1
Parameter Types: []

Constructor Name: MyClass
Modifiers: 2
Parameter Types: [int]

4. リフレクションによるメンバ変数の取得

リフレクションを使用してメンバー変数を取得するには、次の手順に従います。

  1. ターゲット クラスの Class オブジェクトを取得する: メソッドClass.forName()obj.getClass()メソッド、またはクラス名.class を直接使用して、ターゲット クラスの Class オブジェクトを取得します。ターゲットクラスが であると仮定しますMyClass

  2. Class オブジェクトを使用してメンバー変数を取得します。 Class オブジェクトのgetField()メソッドを呼び出してgetDeclaredField()メンバー変数オブジェクトを取得します。これらのメソッドは、それぞれパブリック メンバー変数とすべてのメンバー変数 (プライベート メンバー変数を含む) を取得するために使用されます。

  3. メンバー変数の操作:メンバー変数 object のメソッドを通じてget()メンバー変数の値を取得するか、set()メソッドを通じてメンバー変数の新しい値を設定します。

以下は、リフレクションを使用してメンバー変数を取得し、それを操作する方法を示すサンプル コードです。

import java.lang.reflect.Field;

public class Main {
    public static void main(String[] args) {
        try {
            // 步骤1:获取目标类的Class对象
            Class<?> cls = MyClass.class;

            // 步骤2:获取成员变量
            Field field = cls.getDeclaredField("name");

            // 步骤3:操作成员变量
            // 设置访问权限
            field.setAccessible(true);

            // 获取成员变量的值
            Object instance = cls.newInstance();
            Object value = field.get(instance);
            System.out.println("原始值:" + value);

            // 设置新值
            field.set(instance, "New Value");
            System.out.println("修改后的值:" + field.get(instance));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyClass {
    private String name = "Original Value";
}

上記のサンプル コードを実行すると、次の結果が出力されます。

原始值:Original Value
修改后的值:New Value

この例では、まずMyClass.class対象クラスの Class オブジェクトを取得しますMyClass次に、Class オブジェクトのメソッドを使用して、getDeclaredField()「name」という名前のプライベート メンバー変数の Field オブジェクトを取得します。次に、Field オブジェクトのsetAccessible(true)メソッドを通じてアクセス許可を設定し、プライベート メンバー変数へのアクセスを許可します。最後に、Field オブジェクトのメソッドを通じてメンバー変数の値を取得しget()set()メソッドを通じて新しい値を設定します。

メンバ変数の取得や操作の過程でNoSuchFieldExceptionやIllegalAccessExceptionなどの例外がスローされる場合があり、例外を適切に処理する必要があることに注意してください。

リフレクションを通じてメンバー変数を取得すると、実行時にオブジェクトの属性値に動的にアクセスして変更できます。これは、一部の特定の需要シナリオでは非常に役立ちます。ただし、これは注意して使用し、反映メカニズムの悪用を避けてください。

5. 反射光の取得方法

 以下は、リフレクションを使用してメンバー メソッドを取得し、それを呼び出す方法を示すサンプル コードです。

import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) {
        try {
            // 步骤1:获取目标类的Class对象
            Class<?> cls = MyClass.class;

            // 步骤2:获取成员方法
            Method method = cls.getDeclaredMethod("printMessage", String.class);

            // 步骤3:调用成员方法
            Object instance = cls.newInstance();
            method.invoke(instance, "Hello, Reflection!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyClass {
    private void printMessage(String message) {
        System.out.println("Message: " + message);
    }
}

上記のサンプル コードを実行すると、次の結果が出力されます。

Message: Hello, Reflection!

この例では、まずMyClass.class対象クラスの Class オブジェクトを取得しますMyClass次に、Class オブジェクトのメソッドを使用して、getDeclaredMethod()「printMessage」という名前のプライベート メンバー メソッドの Method オブジェクトを取得します。次に、invoke()Method オブジェクトのメソッドを通じてメンバー メソッドが呼び出されます。

6. まとめ

 

Java リフレクションは、クラスのメンバー (コンストラクター、フィールド、メソッドを含む) を実行時に動的に取得して操作できるようにする強力なメカニズムです。Java リフレクションの概要は次のとおりです。

  1. Class オブジェクトの取得:Class.forName()メソッド、obj.getClass()メソッド、またはクラス名.class を直接使用して、ターゲット クラスの Class オブジェクトを取得します。

  2. コンストラクター メソッドを取得する: Class オブジェクトのgetConstructor()メソッドまたはメソッドを呼び出して、コンストラクター メソッド オブジェクトgetDeclaredConstructor()を取得します。これらのメソッドは、それぞれパブリック コンストラクターとすべてのコンストラクター (プライベート コンストラクターを含む) を取得するために使用されます。

  3. インスタンス オブジェクトの作成:newInstance()コンストラクター メソッド オブジェクトのメソッドを使用して、コンストラクター メソッドのインスタンス オブジェクトを作成します。

  4. メンバー変数の取得: Class オブジェクトのgetField()メソッドまたはメソッドを呼び出して、メンバー変数オブジェクトを取得しますgetDeclaredField()これらのメソッドは、それぞれパブリック メンバー変数とすべてのメンバー変数 (プライベート メンバー変数を含む) を取得するために使用されます。

  5. メンバー変数の操作:メンバー変数 object のメソッドを通じてget()メンバー変数の値を取得するか、set()メソッドを通じてメンバー変数の新しい値を設定します。

  6. メンバー メソッドの取得: Class オブジェクトのgetMethod()メソッドを呼び出して、getDeclaredMethod()メンバー メソッド オブジェクトを取得します。これらのメソッドは、それぞれパブリック メンバー メソッドとすべてのメンバー メソッド (プライベート メンバー メソッドを含む) を取得するために使用されます。

  7. メンバー メソッドの呼び出し:invoke()メンバー メソッド オブジェクトのメソッドを通じてメンバー メソッドを呼び出します。

リフレクションを使用すると、実行時にクラスのメンバーを動的に取得して操作できます。柔軟性が高く、依存関係の挿入、ORM フレームワーク、動的プロキシなどの多くのシナリオに適用できます。

ただし、リフレクションはパフォーマンスの低下を引き起こす可能性があり、特殊なケースではカプセル化やセキュリティが破壊される可能性があるため、注意して使用する必要があります。したがって、リフレクションを使用する場合はベスト プラクティスに従い、必要に応じて長所と短所を比較検討する必要があります。

おすすめ

転載: blog.csdn.net/weixin_55772633/article/details/132380477