In depth explanation of reflection mechanism in Kotlin

  • 2021-10-16 05:06:31
  • OfStack

Preface

The reflection mechanism in Java enables us to obtain the constructor, member variable, member function and other information in the bytecode file of Java class at runtime. This 1 characteristic makes the reflection mechanism often used in the framework. To understand the reflection in Kotlin systematically, we should start with the reflection in Java.

Reflection in Java

Usually we write a good. java source file, through the compilation of javac, finally generated. class bytecode file. These bytecode files are independent of the platform. When using them, they are loaded through Classloader. class bytecode files, so that the program can run according to the business logic we wrote. The reflection of Java mainly gets what we want from these. class files, so what can the reflection of Java get?

Get an Class object

Java is an object-oriented language, and the same. class bytecode file is no exception. If you want to get the contents of. class file, you must first get the Class object corresponding to. class file. There are three ways to get Class objects in Java.


//1.Class.forName(" Class name string ")  (Note: The class name string must be the full name, package name + Class name) 
Class baseInfo = Class.forName("top.sguotao.ReflectionJava");
 //2. Class name .class
Class object = Object.class;
//3. Instance object .getClass()
Class date = (new Date()).getClass();
Class testclass = this.getClass();

Gets the constructor Constructor of the class

Once you get the Class object, you can get the constructor to create the instance object. The constructor of the class corresponds to java. lang. reflect. Constructor. There are five ways to get constructors:


 // 1. Gets the parameter list is parameterTypes The access control character is public Constructor of 
 public Constructor getConstructor(Class[] parameterTypes)

 // 2. Gets all access control characters are public Constructor of 
 public Constructor[] getConstructors()

 // 3. Gets the parameter list is parameterTypes And is the constructor declared by the class itself, and the access control character contains public , protected And private The function of. 
 public Constructor getDeclaredConstructor(Class[] parameterTypes)

 //4. Gets all the constructors declared by the class itself, and the access control character contains public , protected And private The function of. 
 public Constructor[] getDeclaredConstructors()

 //5. If the class is declared in the constructor of another class, return the constructor in which the class is located, if it exists, and if it does not exist, return null
 public Constructor getEnclosingConstructor()

Gets the member variables of the class

The member variables of the class correspond to java. lang. reflect. Field, and there are four ways to obtain the member variables:


 //1. Gets the name is name " public Member variables of ( Includes all the classes that inherit from the base class and are implemented from the interface public Member variable )
 public Field getField(String name)

 //2. Gets all of the public Member variable ( Includes all the classes that inherit from the base class and are implemented from the interface public Member variable )
 public Field[] getFields()

 //3. Gets the name is name "And is a member variable declared by the class itself, containing public , protected And private Member variable. 
 public Field getDeclaredField(String name)

 //4. Gets all the member variables declared by the class itself, including public , protected And private Member variable. 
 public Field[] getDeclaredFields()

Gets the member function of a class

The member function of the class corresponds to java. lang. reflect. Method. There are five ways to obtain the member function:


// 1. Gets the function name is name The parameter is parameterTypes Adj. public Function of ( Includes all the classes that inherit from the base class and are implemented from the interface public Function )
 public Method getMethod(String name, Class[] parameterTypes)

 //2. Gets all of the public Function of ( Includes all the classes that inherit from the base class and are implemented from the interface public Function )
 public Method[] getMethods()

 //3. Get the function name name The parameter is parameterTypes And is a function declared by the class itself, containing public , protected And private Method. 
 public Method getDeclaredMethod(String name, Class[] parameterTypes)

 //4. Gets all the functions declared by the class itself, including public , protected And private Method. 
 public Method[] getDeclaredMethods()

 //5. If this class is an inner class of a method in another class, call getEnclosingMethod() Is the method where this class is located; If it does not exist, return null . 
 public Method getEnclosingMethod()

Get additional information about the class

Getting the annotation information of a class corresponds to the interface java. lang. annotation. Annotation. There are three ways to get the annotation information of a class:


//1. Object of the class annotationClass Annotation of type  ( Includes all the classes that inherit from the base class and are implemented from the interface public Member variable )
public Annotation<A> getAnnotation(Class annotationClass)

//2. Get all the annotations of the class  ( Includes all the classes that inherit from the base class and are implemented from the interface public Member variable )
public Annotation[] getAnnotations()

//3. Get all the annotations of the class's own declaration  ( Include public , protected And private Member variable )
public Annotation[] getDeclaredAnnotations()

Obtain the information of the class interface and base class, which corresponds to the interface java. lang. reflect. Type. There are two methods to obtain the information of the class interface and base class:


 //  Gets all interfaces implemented 
public Type[] getGenericInterfaces()

//  Get the base class 
public Type getGenericSuperclass()

Gets additional description information for the class.


 //1. Get the class name 
 public String getSimpleName()

 //2. Get the full class name 
 public String getName()

 //3. Determine whether the class is an enumeration class 
 public boolean isEnum()

 //4. Judge obj Is it an instance object of a class 
 public boolean isInstance(Object obj)

 //5. Determine whether a class is an interface 
 public boolean isInterface()

 //6. Judge whether a class is a local class, the so-called local class , Is a class defined inside a method. 
 public boolean isLocalClass()

 //7. Judge whether a class is a member class, the so-called member class , Is the common inner class, which refers to the inner class that is not in the code block, constructor and member method. 
 public boolean isMemberClass()

 //8. Determine whether the class is a basic type.   Basic types, including void And boolean , byte , char , short , int , long , float  And  double These types. 
 public boolean isPrimitive()

Reflection in Kotlin

In Kotlin, the class corresponding to bytecode is kotlin. reflect. KClass. Because Kotlin is 100% compatible with Java, reflection in Java can be used in Kotlin. However, since bytecode.class in Kotlin corresponds to KClass class, if you want to use reflection in Java, you need to get an instance of Class first. In Kotlin, you can get an instance of Class in the following two ways.


//1. Through examples .javaClass
var hello = HelloWorld()
hello.javaClass

 //2. Through the class Kclass Class .java Attribute 
HelloWorld::class.java

Once you get the Class instance, you can call the methods described above to get information about the various classes defined in Java.

Of course, in addition to the reflection in Java, Kotlin can also use some methods declared in Kotlin, which is the same as reflection in Java. If you want to use these methods, you must first obtain Kclass objects. In Kotlin, you can obtain Kclass instances in the following two ways.


 //1. Through the class ::class Obtain the way of Kclass Instances 
val clazz1: KClass<*> = HelloWorld::class
//2. Through examples .javaClass.kotlin Get Kclass Instances 
var hello = HelloWorld()
val clazz2 = hello.javaClass.kotlin

Once you get an instance of Kclass, you can call some of the methods declared in Kotlin about reflection. What are the methods?

Constructor Constructor

Kotlin can get all the constructors in the following way.


// Returns all constructors for this class 
public val constructors: Collection<KFunction<T>>

Member variables and member functions

There are six methods to get member variables and member functions in Kotlin.


 // 1. Gets the parameter list is parameterTypes The access control character is public Constructor of 
 public Constructor getConstructor(Class[] parameterTypes)

 // 2. Gets all access control characters are public Constructor of 
 public Constructor[] getConstructors()

 // 3. Gets the parameter list is parameterTypes And is the constructor declared by the class itself, and the access control character contains public , protected And private The function of. 
 public Constructor getDeclaredConstructor(Class[] parameterTypes)

 //4. Gets all the constructors declared by the class itself, and the access control character contains public , protected And private The function of. 
 public Constructor[] getDeclaredConstructors()

 //5. If the class is declared in the constructor of another class, return the constructor in which the class is located, if it exists, and if it does not exist, return null
 public Constructor getEnclosingConstructor()
0

Class related information

You can see that in Kotlin reflection, you can get more information about classes than in Java reflection.


 // 1. Gets the parameter list is parameterTypes The access control character is public Constructor of 
 public Constructor getConstructor(Class[] parameterTypes)

 // 2. Gets all access control characters are public Constructor of 
 public Constructor[] getConstructors()

 // 3. Gets the parameter list is parameterTypes And is the constructor declared by the class itself, and the access control character contains public , protected And private The function of. 
 public Constructor getDeclaredConstructor(Class[] parameterTypes)

 //4. Gets all the constructors declared by the class itself, and the access control character contains public , protected And private The function of. 
 public Constructor[] getDeclaredConstructors()

 //5. If the class is declared in the constructor of another class, return the constructor in which the class is located, if it exists, and if it does not exist, return null
 public Constructor getEnclosingConstructor()
1

Problems of Reflection Attention in Using Kotin

If String, Map, List and other types are reflected in Kotlin 1.1, an built-in Kotlin Types exception will be thrown because these types have not been supported in Kotlin 1.1, and this problem has been solved in Kotlin 1.2.

The content of Kotlin about reflection is put in jar package of kotlin-reflect. This jar package has 2.6 M, which needs to occupy 1 memory space for mobile development.

Finally, it is about the efficiency of Kotlin reflection. It takes about 10 microseconds to reflect in Java, hundreds or even thousands of microseconds in Kotlin, and even tens of thousands of microseconds to access objects or construct attributes through reflection. The official explanation is that there is no energy to optimize at present, and I believe the efficiency will be improved in subsequent versions.

Reference link

Kotlin Bootcamp for Programmers Kotlin Koans

Summarize


Related articles: