java.lang.reflectパッケージの浅い分析

4916 ワード

Object(ソース)
Javaはすべて対象です
Objectは反射の元
Classは反射の監督です
Class(監督)
Javaプログラムが実行されると、JVMはすべてのオブジェクトに対してユニークなタイプIDを維持します.これがClassオブジェクトです.
Javaの基本タイプとキーワードvoidもクラスオブジェクトに対応しています.同じ要素タイプと次元の配列もClassオブジェクトに対応します.
Classオブジェクトを取得する方法:
  • のオブジェクトが通過する.class
  • オブジェクトはgetClassメソッド
  • を介して
  • Class.forName(String)

  • Classオブジェクトにはいくつかの重要な方法があります.
  • getConstructorシリーズ、構築方法
  • を取得するために使用される
  • getFieldシリーズ、属性
  • を取得するために使用される
  • getMethodシリーズ、取得方法
  • 上記のシリーズにはDeclaredシリーズが含まれており、現在のオブジェクトのすべてのタイプの反射(privateを含む)を取得できますが、親の反射は取得できません.
    Constructor、Field、MethodはClass監督の3つの利器で、いずれもjava.lang.reflectパックの下にあり、次はそれぞれこの3つの利器を展示します.
    Constructor
    Classオブジェクトで取得したConstructorオブジェクトの後、最も一般的な操作はオブジェクトをインスタンス化し、newInstanceメソッドを呼び出すことです.
    実はClassオブジェクトにもnewInstanceメソッドがあり、オブジェクトをインスタンス化するのにも使えますが、その違いは何ですか?
  • Class.NewInstance()は、非パラメトリック構造関数、すなわちデフォルトの構造関数のみを呼び出すことができ、呼び出された構造関数が可視であること、すなわちpublicタイプであることが要求される.
  • Constructor.NewInstance()は、入力されたパラメータに基づいて任意の構造構造関数を呼び出すことができ、特定の場合、プライベートな構造関数を呼び出すことができる.

  • Demo
    //Class.newInstance()
    //    public           
    A a = (A)Class.forName(A.class.getName()).newInstance();  
    
    //Constructor.newInstance()
    Class c= Class.forName(A.class.getName());
       
    /*       、      */  
    //      
    Constructor c0=c.getDeclaredConstructor();  
    //           
    c0.setAccessible(true);   
    A a0=(A)c0.newInstance();
        
    //        ,      
    /*       、      */   
    Constructor c1=c.getDeclaredConstructor(new Class[]{int.class,int.class});   
    c1.setAccessible(true);   
    //        ,       
    A a1=(A)c1.newInstance(new Object[]{5,6});   
    
    

    シーンを使用:
    インタフェースモードを使用する場合、newを使用してドアのオブジェクトを作成します.Door door=new WoodenDoor()です.他のドアに変更する場合は、コードを変更する必要があります.Door door=new OtherDoor()です.したがって、ファクトリモデルを使用し、必要なドアを使用してドアを生産する必要があります.newInstance()メソッドを使用して生産する場合は、プロファイルを変更するだけです.
    Field
    Classオブジェクトで取得したFieldオブジェクトを使用すると、オブジェクトのプロパティ値を自由に表示および設定できます.
    主な方法:
  • get(Object object)特定オブジェクトの属性値を表示する
  • set(Object object,Object value)特定オブジェクトに属性
  • を設定する.
  • setAccessible(boolean flag)privateメンバーにpublic権限を持たせる
  • Demo
    //  Class  
    Class aClass = MyObject.class
    //  Class    Field  
    Field field = aClass.getDeclaredField("someField");
    //       
    field.setAccessible(true);
    
    MyObject objectInstance = new MyObject();
    
    //             
    Object value = field.get(objectInstance);
    //            
    field.set(objetInstance, value);
    

    Constructor、Field、MethodはすべてAccessibleObject類から受け継がれているため、すべてsetAccessibleの方法を持っていて、個人的にsetAccessibleは少しプライバシーを覗いている感じがして、ハハハ、Class監督がどう見ているか分かりません.
    Method
    Classオブジェクトで取得したMethodオブジェクトの後、考えなくてもいいですよ.メソッドを取得して何を呼び出さないのか、私たちが最もよく使う操作はinvokeメソッドです.
    皆さんはinvokeに慣れていないと思います.多くの異常のため、最後にinvoke方法に位置づけられます.
    java.lang.NullPointerException
      at ......
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
    

    invoke(Object receiver,Object...args)は、receiverパラメータを渡す方法と、nullを渡す方法の2つに分けられます.
    //        doSomesthing,     String   
    Method method = MyObject.class.getMethod("doSomething", String.class);
    
    //     doSomesthing  ,    "parameter-value1"
    Object returnValue = method.invoke(null, "parameter-value1");
    

    最後に一言
    本稿では,Clssオブジェクトおよびreflectパケット下のオブジェクトの簡単な使用説明にすぎず,反射の実現と原理については,さらに深く検討する必要がある.例えば、AccessibleObjectオブジェクトおよび対応するxxxAccessorの実装.