Before the order
When using reflection in Kotlin, you are dealing with two different reflection apis.
- Standard Java reflection, defined in packages
java.lang.reflect
In the. Because Kotlin classes are compiled into plain Java bytecode, the Java reflection API supports them perfectly. - Kotlin reflection API, defined in the package
kotlin.reflect
In the. The Kotlin Reflection API gives you access to concepts that don’t exist in the Java world, such as properties and nullable types. The Kotlin Reflection API is not an alternative to the Java Reflection API. Meanwhile, the Kotlin reflection API is not limited to Kotlin classes; classes written in any JVM language can be accessed using the same API.
Class reference
The most basic reflection function is to get a runtime reference to the Kotlin class.
val daqiKotlinClass = daqiKotlin::class
Copy the code
Kotlin’s class reference is actually a value of type KClass. If you want to get a Java class reference, you can use.java property retrieval on a KClass instance.
For a Java class reference, you can convert it to a Kotlin class reference using. Kotlin
val daqiKotlinJavaClass = daqiKotlin::class.java
val daqiKotlinaClass = daqiKotlinJavaClass.kotlin
Copy the code
Properties or functions | meaning |
---|---|
memberProperties | Non-extended attributes declared in this class and all of its superclasses |
memberFunctions | Non-extended non-static functions declared in this class and all of its superclasses |
members | Non-extended non-static functions and properties declared in this class and all of its superclasses, excluding constructors |
constructors | All constructors |
isFinal | Final class |
isOpen | Class open |
isAbstract | Abstract class |
isSealed | Is it sealed? |
isData | Data class |
isInner | Inner class |
isCompanion | Whether it is an associated object |
Introduce Kotlin reflection
On the Java platform, the runtime components required to use reflection are distributed as separate JAR files (kotlin-reflect.jar). This is done to reduce the size of the runtime libraries required by applications that do not use reflection. If you need to use reflection, make sure the.jar file is added to your project’s classpath.
Add the Kotlin reflection JAR to Gradle (see here) :
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"// Add Kotlin reflection JAR package implementation"org.jetbrains.kotlin:kotlin-reflect"
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
}
Copy the code
KCallable
In Kotlin’s class reference KClass, attributes and functions are stored in the KCallable collection Members, while constructors are stored in the KFunction collection Constructors. The superinterface of KFunction is KCallable, that is, KCallable is the superinterface of functions (including constructors) and attributes.
KCallable declares the call method, which allows you to call the corresponding function or the getter for the corresponding property:
public actual interface KCallable<out R> : KAnnotatedElement { public fun call(vararg args: Any?) : R ..... }Copy the code
Function KFunction
When we learned about lambda, we learned about method references, which use the :: operator to refer to methods and return a KFunction object.
For KFunction objects, the KCallable#call method can be used to call the referenced function. But ::daqi is also an object of type KFunctionN (N stands for a specific number of arguments, similar to lambda’s Function), and the reference Function can be called via the invoke method. (Since the invoke method is an Openator method, the convention can use () instead to call the invoke method)
fun main(){
val func = ::daqi
func.invoke("")
func.call("")
}
fun daqi(name:String){
}
Copy the code
The difference between KCallable#call and KFunctionN#invoke is that the parameter type and return value type of KFunctionN#invoke are determinable and can be checked by the compiler. If the argument type and number do not match invoke, the compiler will not compile. KCallable#call is valid for all types, which means that the developer needs to match the corresponding argument type and number, otherwise it will get an exception at runtime.
Each KFunctionN type inherits KFunction with an additional invoke with just the right number of arguments. For example: KFunction2 declares Openator Fun Invoke (P1 :P1, P2 :P2):R. The KFunctionN types are synthesized compiler-generated types and their declarations cannot be found in the package kotlin.reflect. Means a function interface that can use any number of parameters.
Attribute KProperty
KProperty differs from Java’s Field, which generally refers to the Field itself, in that it stands for the corresponding Getter and Setter.
KProperty can represent any property, and its subclass, KMutableProperty, can represent a variable declared by var.
The supertype of KProperty is also KCallable, meaning that when you get the property, you can also use KCallable# Call, which calls the getter for the property. But Kotlin’s attribute interface provides a better way to get attribute values: the get method.
KProperty0<out R>
Provided is a no-parameterget
Method whose type parameter represents the type of the property;
Top-level attributes, for example, are referenced directly using the :: operator. Because the receiver is not required, the property reference is of type KProperty0.
val name = "daqi"
fun main(){
val property = ::name
property.get()
property.call()
}
Copy the code
KProperty1<T, out R>
Provide one that requires a receiverget
Method, where one type parameter represents the type of the receiver and the second type parameter represents the type of the property;
For example, a member property or an extended property requires a concrete recipient instance whose property reference is of type KProperty1
fun main(){
val property = daqiKotlin::name
val daqi = daqiKotlin()
property.get(daqi)
}
class daqiKotlin{
val name = ""
}
Copy the code
Attribute references can only be used to define attributes in an outer layer or class, not local variables.
As a subclass of KProperty, KMutableProperty provides a set method in addition to the corresponding GET method.
fun main(){
val property = daqiKotlin::name
val daqi = daqiKotlin()
property.get(daqi)
property.set(daqi,"")
property.call(daqi)
}
class daqiKotlin{
var name = ""
}
Copy the code
The call method of a KMutableProperty instance is still the getter that calls that property.
The last
The Kotlin Basics series concludes with this chapter. Along the way, I have clarified many of the concepts myself, and the Kotlin basics have become more solid. At the same time, I also know that MY writing style is rough, and I will improve step by step in the future to make it easier for readers to understand the content of the article.
Here are three excellent Kotlin articles:
- Exploring hidden Costs in Kotlin (Part I)
- Exploring hidden Costs in Kotlin (Part II)
- Exploring Kotlin’s Hidden Costs (Part 3)
References:
- Kotlin in Action
- Kotlin website
Android Kotlin series:
Kotlin’s Knowledge generalization (I) — Basic Grammar
Kotlin knowledge generalization (2) – make functions easier to call
Kotlin’s knowledge generalization (iii) — Top-level members and extensions
Kotlin knowledge generalization (4) – interfaces and classes
Kotlin’s knowledge induction (v) — Lambda
Kotlin’s knowledge generalization (vi) — Type system
Kotlin’s knowledge induction (7) — set
Kotlin’s knowledge induction (viii) — sequence
Kotlin knowledge induction (ix) — Convention
Kotlin’s knowledge induction (10) — Delegation
Kotlin’s knowledge generalization (xi) — Higher order functions
Kotlin’s generalization of knowledge (xii) – generics
Kotlin’s Generalization of Knowledge (XIII) — Notes
Kotlin’s Knowledge induction (xiv) — Reflection