JAva反射---高度な開発に必要な入門知識


JAva反射とは、JVM(java仮想マシンの略称)にマウントされているjavaのオブジェクトにアクセスしたり、そのオブジェクト自体の情報を検出したり修正したりする反射メカニズムのことです.反射メカニズムの機能はjavaで非常に強力と言える.lang.reflectパッケージのクラスは、これらの機能をサポートしています.
反射といえば私たちが迂回できないクラスClassですが、それはいったい何ですか?実は対象の世界の中で万事万物はすべて対象で、類も例外ではありません;実行中のjava仮想マシンのクラスはすべてClassクラスのオブジェクトです.クラスもオブジェクトで、クラスはjavaです.lang.Classクラスのインスタンスオブジェクト.
このクラスクラスのオブジェクト(このオブジェクトがクラスであることに注意してください.javaのjdkに付属しているクラスであっても、私たちが作成したクラスであってもよいことに注意してください).このオブジェクトによって、作成したインスタンスオブジェクトの基本情報を知ることができます.これが反射機構の直接表現形式である.このように言うと少し拗ねるかもしれませんが、以下に例を挙げます.例えば、public class A{}があり、A a=new A();Aクラスのオブジェクトaを作成しました.
 Class clz=a.getClass();//     Class       clz

 //            clz,           a       :    ,    ,  ,          

反射メカニズムの一般的な理解について話しただけで、分かりましたか?次はコードで勉強します
1.まずClassクラスのオブジェクトをどのように取得しますか?次の3つの方法があります.
package com.csdn;

class Person {}//Person 

public class T {

    public static void main(String[] args) throws ClassNotFoundException {
        Person mPerson = new Person();

        //      (                  class)
        Class p1 = Person.class;

        //      (     Person      ,    mPerson)
        Class p2 = mPerson.getClass();

        //      (Class.forName("    "),    )
        Class p3 = Class.forName("com.csdn.Person");
        System.out.println(p1 == p2);//    true
        System.out.println(p2 == p3);//    true
    }

}

p 1も印刷され、p 2とp 3のスタックメモリの比較結果はtrueであり、結果は彼らが同じであることを証明した.結果は、Classクラスのあるオブジェクト(クラス)も唯一であることを示しています.上記の3つの方法は、どちらを通じて得られたPersonクラスも同じであることは理解できます.JVMでは私たちのクラスは1つであり、2つの同じクラスは存在しない可能性があるからです.
2.反射に関するいくつかのクラスを紹介します.もちろんたくさんありますが、ここではよくあるものをいくつか挙げます.
Fieldクラス:オペレーティングクラスの属性Methodクラス:オペレーティングクラスのメソッドConstructorクラス:単一の構築メソッドを提供する情報Modifierクラス:アクセス修飾子(クラスとメンバー変数のアクセス修飾子)を復号するために使用され、このクラスはすべて整数定数です.各定数はアクセス修飾子を表します.
3.メソッドを反射して呼び出します.ここではMethodクラス(メソッドオブジェクト)に使用します.メンバーメソッドはMethodのインスタンスオブジェクトです.上のPersonクラスにメソッドを追加
class Person {
    private int height;

    private int addHeight(int a) {
        height = a + 1;
        return height;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}

次にMethodクラスで操作するか、p 1を次に使用するか
        Class<?> p1 = Person.class;
        // getDeclaredMethods()                 
        Method[] mds = p1.getDeclaredMethods();
        System.out.println("        : ");

        for (int i = 0; i < mds.length; i++) 
        {
            //            
            int mModify = mds[i].getModifiers();
            // Modifier                
            //      public static final int PRIVATE =0x2    private
            //   Modifier.toString()          String      private
            System.out.print(Modifier.toString(mModify) + " ");

            //           
            Class<?> mReturnType = mds[i].getReturnType();
            System.out.print(mReturnType.getName());

            //        
            String mMethodName = mds[i].getName();
            System.out.print(" " + mMethodName);

            //          
            Class<?>[] mParamType = mds[i].getParameterTypes();
            System.out.print("(");
            //                 
            if (mParamType.length == 0)
                System.out.println(")");
            for (Class<?> mClass : mParamType) {
                //          
                System.out.print(mClass.getName());
                System.out.println(")");
            }

        }

印刷結果は次のとおりです.
        : 
public void setHeight(int)
public int getHeight()
private int addHeight(int)

ここではちょうど上記のPersonクラスの3つの方法を見ることができ、Methodクラスを通じて方法情報をよく取得することができます.実際にはMethodクラスを通じてこの方法を呼び出すこともできます.ここではprivate修飾でオブジェクトオブジェクトを直接呼び出すことはできません.反射を利用して簡単にできます.例えばprivate int addHeight(int a)メソッドに実パラメータ値が2であることを伝えます.操作は以下の通りです.
Class<?> p1 = Person.class;
Person mPerson = new Person();

//             ,             ,         Class  
Method md = p1.getDeclaredMethod("addHeight", int.class);

//          ,    
md.setAccessible(true);

//   invoke           Person    ,         
int returnValue = (Integer) md.invoke(mPerson, 2);//retrunValue addHeight(int a)       

System.out.println("   : " + returnValue);
System.out.println("  mPerson     :"+mPerson.getHeight());

印刷結果は
   : 3
  mPerson     :3

4.Fieldクラスを使用して属性を操作するFieldクラスインスタンスがメンバー変数を表す
        Class<?> p1 = Person.class;

        System.out.println("       : ");
        //            
        Field[] mFields = p1.getDeclaredFields();

        for (int i = 0; i < mFields.length; i++) 
        {
            //            
            System.out.print(Modifier.toString(mFields[i].getModifiers()) + " ");

            //        
            System.out.print(mFields[i].getType().getName() + " ");

            //        
            System.out.println(mFields[i].getName());
        }


印刷結果:
       : 
private int height

もちろん同じ方法でも、Fieldで直接変数に値を付けることができます.
        Class<?> p1 = Person.class;
        Person mPerson = new Person();
        //             ,        
        Field mField = p1.getDeclaredField("height");

        //            ,        
        mField.setAccessible(true);

        //   setInt    height     2,   int     setInt
        mField.setInt(mPerson, 2);

        System.out.println("mPerson height    :" + mPerson.getHeight());

印刷結果:
mPerson height    :2

5.コンストラクションメソッドを操作するにはConstructorクラスを使用します.コンストラクションメソッドのインスタンスは、コンストラクションメソッドオブジェクトを表し、Personクラスに次のコンストラクションメソッドを追加します.
public Person() {
        super();
    }

    private Person(int height) {
        super();
        this.height = height;
    }

次にConstructorクラスを用いて構築方法を操作し,次にp 1を用いる.
        Class<?> p1 = Person.class;
        System.out.println("       :");

        //              
        Constructor<?>[] mCons = p1.getDeclaredConstructors();
        for (int i = 0; i < mCons.length; i++) 
        {

            //              
            System.out.print(Modifier.toString(mCons[i].getModifiers()) + " ");
            System.out.print(mCons[i].getName());

            //            
            Class<?>[] mConsClass = mCons[i].getParameterTypes();
            System.out.print("(");
            for (Class<?> css : mConsClass) {
                System.out.print(css.getName());
            }
            System.out.println(")");
        }

印刷結果:
        :
public com.csdn.Person()
private com.csdn.Person(int)

もちろんConstructorでPersonクラスのオブジェクトを作成することもできます
         Class<?> p1 = Person.class;
        Constructor<?>[] mConstructs = p1.getDeclaredConstructors();
        System.out.println(mConstructs.length);
        for (int i = 0; i < mConstructs.length; i++) { if (i == 0) {//          Person person1 = (Person) mConstructs[i].newInstance(); System.out.println("           Height  :"+person1.getHeight()); } else if (i == 1) 
            {//          mConstructs[i].setAccessible(true); Person person2 = (Person) mConstructs[i].newInstance(2); System.out.println("           Height  :"+person2.getHeight()); }
        }

印刷結果は次のとおりです.
           Height  :0
           Height  :2

説明:p 1.getDeclaredConstructors()で得られた配列における構造方法の順序は,構造方法がPersonクラスにおける宣言順に並べられているが,Personクラスではまず無参,後に有参であるため,得られた配列の最初の要素は無参構造方法を表し,2番目の要素は有参構造方法である上では科学的ではないが,ここではデモのために,Personがこのように書いたのは2つの構造方法しかないことを知っています.2つ目はpublic修飾の構造方法ではないのでsetAccessibleを使用してアクセス権を破る.
ここまで反射メカニズムの基礎知識も紹介しましたが、皆さんに役に立つことを望んでいます.