【Javaベース】Javaでの反射メカニズム

4072 ワード

一、反射の理解
(1)正射は発射という概念を導入する前に,まず「正射」を理解する必要がある.一般的に、あるクラスを使用するときは、それがどんなクラスなのか、何に使われているのか、どのような機能を持っているのかを知る必要があります.そこで、このクラスをインスタンス化してから、インスタンス化されたオブジェクトを使用してこのクラスを操作することができます.
Person person = new Person();
person.sleep("8:00");
(2)反射上の例では,「正射」とは何か,および「正射」の一般例を簡単に紹介した.反射は、最初は初期化するクラスが何なのか分からないので、newキーワードを使ってオブジェクトを作成することはできません.このクラスの名前を入手できる場合、JDKが提供する反射APIを使用して反射呼び出しを行うことができます.
Class clazz = Class.forName("com.reflect.Person");
Method method = clazz.getMethod("sleep", String.class);
Constructor constructor = clazz.getConstructoer();
Object object = constructor.newInstance();
method.invoke(object, "8:00");
以上の2つのコードは、結果は一致していますが、その考え方はまったく異なります.
  • 第1セグメントコードは、実行前に実行するクラス(Person)を決定した.
  • の第2セグメントコードは、プログラム全体の実行時に特定の場所(例:プロファイル)から対応する文字列値を取得してこそ、実行するクラス(cn.reflect.Person)を知ることができる.
  • 二、反射の応用
    (1)Tomcatのクラス読み込み作成:
    
            ChatServlet
            chat.ChatServlet
        
    
            ChatServlet
            /servlets/chat/chat
    
    
    以上のように、HTTP要求が来た場合、サーブレットコンテナはまずマッパーで対応するサーブレットクラスを選択し、web.xmlプロファイルのクラスのアドレスでサーブレットオブジェクトをインスタンス化し、固定されたメソッド名でサーブレットのメソッドを呼び出す.
    三、反射における常用関数
    (1)反射中のclassオブジェクトを取得反射中にクラスを取得する方法またはクラスを呼び出す方法は、まずそのクラスのオブジェクトを取得する必要があります.Java APIでClassクラスオブジェクトを取得するには、①Class.forName("-クラスのパス名-");
    Class clazz = Class.forName("com.reflect.Person");
    
    ②:クラスオブジェクトを持つgetClass()メソッドを利用する.
    Person person = new Person();
    Class clazz = person.getClass();
    
    ③:コンパイル前から知っているクラスについては.classメソッドを使用できます.
    Class clazz = Person.class;
    
    (2)反射によってクラスオブジェクトを作成し、反射によってクラスオブジェクトを作成するJava APIは2つの方法を提供する:1:Classオブジェクトを通過するnewInstance()方法;
    Class clazz = Class.forName("com.reflect.Person");
    Person person = (Person)clazz.newInstance();
    
    ②:ConstructorオブジェクトによるnewInstance()メソッド
    Class clazz = Class.forName("com.reflect.Person");
    Constructor con = clazz.getConstructor();
    Person person = (Person)con.newInstance();
    
    注意:ConstructorオブジェクトのnewInstance()メソッドでクラスオブジェクトを作成すると、特定のコンストラクション関数を選択できますが、ClassオブジェクトのnewInstance()メソッドでは、デフォルトの非パラメトリックコンストラクション関数しか使用できません.例:
    Class clazz = Class.forName("com.reflect.Person");
    Constructor con = clazz.getConstructor();
    Person person = (Person)con.newInstance("  ");
    
    (3)反射操作によるメンバー変数①:すべてのメンバーgetFields()&getDeclaredFields()はgetFields()メソッドを使用してClassクラスのメンバー変数を取得できますが、プライベート属性は取得できません.
    Class clazz = Class.forName("com.reflect.Person");
    Field[] fields = clazz.getFields();
    for (Field field : fields) {
      System.out.print(field.getName());
    }
    
    ②:単一メンバーgetField()&getDeclaredField()③:メンバーの値set(Object obj,Object value)の変更
    Class clazz = Class.forName("com.reflect.Person");
    Person person = (Person)clazz.newInstance();
    Field field = clazz.getField("name");
    field.set(person, "  ");
    
    プロパティがprivateの場合、値を変更できません.setAccessible()メソッドを使用してアクセス権を取得する必要があります.
    Class clazz = Class.forName("com.reflect.Person");
    Person person = (Person)clazz.newInstance();
    Field field = clazz.getDeclaredField("name");
    field.setAccessible(true);
    field.set(person, "  ");
    
    (4)操作メンバーを反射する方法①:すべての方法getMethods()&getDeclaredMethods()②:単一メンバーgetMethod()&getDeclaredMethod()を取得する操作方法は操作変数と大きく異なり,対応する方法を取得した後にinvoke()メソッドを用いて実行する.同様に,プライベートメソッドに遭遇した場合もsetAccessible(true)メソッドを用いてアクセス権を取得する必要がある.
    Class clazz = Class.forName("com.reflect.Person");
    Person person = (Person)clazz.newInstance();
    Method method = clazz.getMethod("setName", String.class);
    method.setAccessible(true);
    method.invoke("  ");
    
    注意:通常、現在のクラスでもprivateメソッドや属性にはアクセス権がありません.アクセス権を取得するには、圧縮権限setAccessible(true)を設定する必要がありますが、実際にはルールが破壊されているので、できるだけ使用しないでください.