Kotlinでの反射

7916 ワード

ブログアドレスhttps://sguotao.top
Javaの反射メカニズムにより、Javaクラスのバイトコードファイルのコンストラクション関数、メンバー変数、メンバー関数などの情報を実行中に取得できます.この特性は反射機構をフレームワークによく用い,Kotlinにおける反射を系統的に理解するにはJavaの反射から始める.
Javaでの反射
通常、私たちが書いた.javaソースファイルはjavacのコンパイルを経て、最終的に.classバイトコードファイルを生成しました.これらのバイトコードファイルはプラットフォームに関係なく、Classloaderを使用してこれらの.classバイトコードファイルをロードし、プログラムを私たちが作成したビジネスロジックに従って実行します.Javaの反射は主にこれらの.classファイルから私たちが得たいコンテンツを取得しますが、Javaの反射はどのようなコンテンツを得ることができますか?
Classオブジェクトの取得
Javaはオブジェクト向けの言語で、同じ.classバイトコードファイルも例外ではありません..classファイルの内容を取得するには、.classファイルに対応するClassオブジェクトを先に取得します.JavaでClassオブジェクトを取得する方法は3つあります.
//1.Class.forName("     ") (  :          ,  +  )
Class baseInfo = Class.forName("top.sguotao.ReflectionJava");
 //2.  .class
Class object = Object.class;
//3.    .getClass()
Class date = (new Date()).getClass();
Class testclass = this.getClass();

クラスのコンストラクション関数Constructorの取得
Classオブジェクトを取得すると、コンストラクション関数を取得してインスタンスオブジェクトを作成できます.クラスのコンストラクション関数はjava.lang.reflect.constructorに対応します.コンストラクション関数を取得するには、次の5つの方法があります.
    // 1.       parameterTypes,      public     
    public Constructor getConstructor(Class[] parameterTypes)

    // 2.          public     
    public Constructor[] getConstructors()

    // 3.       parameterTypes,             ,       public、protected private   。
    public Constructor getDeclaredConstructor(Class[] parameterTypes)

    //4.               ,       public、protected private   。
    public Constructor[] getDeclaredConstructors()

    //5.               ,           ,       ,     null
    public Constructor getEnclosingConstructor()

クラスのメンバー変数の取得
クラスのメンバー変数はjava.lang.reflect.Fieldに対応し、メンバー変数を取得するには以下の4つの方法があります.
    //1.  “   name” public     (        、        public    )
    public Field getField(String name)

    //2.     public    (        、        public    )
    public Field[] getFields()

    //3.  “   name”,             ,  public、protected private    。
    public Field getDeclaredField(String name)

    //4.               ,  public、protected private    。
    public Field[] getDeclaredFields()

クラスのメンバー関数の取得
クラスのメンバー関数はjava.lang.reflect.Methodに対応しており、メンバー関数を取得するには以下の5つの方法があります.
// 1.      name,   parameterTypes public   (        、        public  )
    public Method getMethod(String name, Class[] parameterTypes)

    //2.     public   (        、        public  )
    public Method[] getMethods()

    //3.     name,   parameterTypes,           ,  public、protected private  。
    public Method getDeclaredMethod(String name, Class[] parameterTypes)

    //4.             ,  public、protected private  。
    public Method[] getDeclaredMethods()

    //5.                  ,  getEnclosingMethod()          ;    ,  null。
    public Method getEnclosingMethod()

クラスのその他の情報の取得
クラスの注釈情報を取得するには、java.lang.annotation.Annotationインタフェースに対応し、クラスの注釈情報を取得するには、次の3つの方法があります.
//1.    annotationClass      (        、        public    )
public AnnotationgetAnnotation(Class annotationClass)
//2.クラスのすべての  (ベースクラスから  されたインタフェースから  されたすべてのpublicメンバー  を む)を  する
public Annotation[] getAnnotations()
//3.クラス  が  したすべての  (public、protected、privateメンバー  を む)を  します。
public Annotation[] getDeclaredAnnotations()

クラスのインタフェースとベースクラスの情報を取得します.java.lang.reflect.Typeインタフェースに対応します.クラスのインタフェースとベースクラスの情報を取得するには、次の2つの方法があります.
 //          
public Type[] getGenericInterfaces()

//     
public Type getGenericSuperclass()

クラスの他の説明情報を取得します.
    //1.    
    public String getSimpleName()

    //2.      
    public String getName()

    //3.         
    public boolean isEnum()

    //4.  obj         
    public boolean isInstance(Object obj)

    //5.        
    public boolean isInterface()

    //6.         ,     ,           。
    public boolean isLocalClass()

    //7.         ,     ,        ,       ,              。
    public boolean isMemberClass()

    //8.          。     ,  void boolean、byte、char、short、int、long、float   double     。
    public boolean isPrimitive()

Kotlinでの反射
Kotlinではバイトコード対応クラスはkotlin.reflect.Kclassであり、KotlinはJavaに100%対応しているため、KotlinではJavaでの反射を利用することができるが、Kotlinではバイトコード.classがKclassクラスに対応しているため、Javaでの反射を利用するにはまずClassのインスタンスを取得する必要があり、Kotlinでは、次の2つの方法でClassインスタンスを取得できます.
//1.    .javaClass
var hello = HelloWorld()
hello.javaClass

 //2.   Kclass  .java  
HelloWorld::class.java

Classインスタンスを取得すると、上記の方法を呼び出し、Javaで定義されているクラスの情報を取得できます.
もちろんKotlinではJavaでの反射に加えてKotlinで宣言されたいくつかの方法を使用することもできますが、もちろんJavaでの反射と同様に、これらの方法を使用するには、まずKclassオブジェクトを取得し、Kotlinでは以下の2つの方法でKclassインスタンスを取得することができます.
 //1.   ::class     Kclass  
val clazz1: KClass = HelloWorld::class
//2.    .javaClass.kotlin  Kclass  
var hello = HelloWorld()
val clazz2 = hello.javaClass.kotlin

Kclassインスタンスを取得すると、Kotlinで宣言された反射に関するいくつかのメソッドを呼び出すことができますが、どのようなメソッドがありますか?
コンストラクション関数Constructor
Kotlinは以下の方法ですべてのコンストラクション関数を取得することができる.
//           
public val constructors: Collection>

メンバー変数とメンバー関数
Kotlinでメンバー変数とメンバー関数を取得する方法は6つあります.
    //              ,        ,        
    override val members: Collection>
    //          
    val KClass.declaredFunctions: Collection>
    //        
    val KClass.declaredMemberExtensionFunctions: Collection>
    //        
    val  KClass.declaredMemberExtensionProperties: Collection>
    //            
    val KClass.declaredMemberFunctions: Collection>
    //            (  )
    val  KClass.declaredMemberProperties: Collection>

クラス関連情報
Kotlin反射では、Java反射よりもクラスに関する情報を多く取得できます.
//1.      
public val simpleName: String?
 //2.       
public val qualifiedName: String?
//3.        object,      ,    null
public val objectInstance: T?
//4.       
@SinceKotlin("1.1")
public val visibility: KVisibility?
//5.      final ( Kotlin ,    final ,        open  abstract)
@SinceKotlin("1.1")
public val isFinal: Boolean
//6.      open (abstract   open ),          
@SinceKotlin("1.1")
public val isOpen: Boolean
//7.         
@SinceKotlin("1.1")
public val isAbstract: Boolean
//8.         ,   : sealed  ,           
@SinceKotlin("1.1")
public val isSealed: Boolean
//9.      data 
@SinceKotlin("1.1")
public val isData: Boolean
//10.         
@SinceKotlin("1.1")
public val isInner: Boolean
//11.      companion object
@SinceKotlin("1.1")
public val isCompanion: Boolean    
//12.          ,     (inner class   )    (class   )
public val nestedClasses: Collection>
 //13.              
@SinceKotlin("1.1")
public fun isInstance(value: Any?): Boolean
//14.          
@SinceKotlin("1.1")
public val typeParameters: List
//15.         
@SinceKotlin("1.1")
public val supertypes: List
//16.        
val KClass.allSuperclasses: Collection>
//17.        companionObject
val KClass.companionObject: KClass?

Kotinで反射する注意の問題を使う
Kotlin 1.1でString,Map,Listなどのタイプを反射するとbuilt-in Kotlin Typesの異常が投げ出されます.これはKotlin 1.1バージョンではこれらのタイプにサポートが追加されていないためです.Kotlin 1.2バージョンでは、この問題は解決されています.
Kotlin反射に関する内容はkotlin-reflectのjarパッケージに入っています.このjarパッケージは2.6 Mあり、モバイル端末の開発には一定のメモリスペースが必要です.
最後に、Kotlin反射の効率についてですが、Javaでは数十マイクロ秒、Kotlinでは数百~数千マイクロ秒、反射によってオブジェクトや構造属性、さらには数万マイクロ秒を必要とします.これについて、公式には、まだ最適化に力を入れていないので、後続のバージョンでは効率の問題が改善されると信じています.
リファレンスリンク
  • Kotlin Bootcamp for Programmers
  • Kotlin Koans