kotlin 反射
Prerequisites:
類別是 KClass
方法是 KFunction
欄位是 KProperty
KClass
getter / setter 是自動產生
主建構子 / 次建構子概念
data class: componentN、自動 equals、hashCode
sealed class
suspend function(會被編譯成不同樣子)
inline class
typealias
companion object(Java 不存在這東西)
Java 的 Class 無法描述這些行為,所以 Kotlin 需要 KClass。
Java Reflection Kotlin KClass 對照表
簡單對映表
| Java Reflection | Kotlin KClass 對應 API |
| getSuperclass() | supertypes |
| getInterfaces() | java.interfaces 或 supertypes 過濾 |
| getFields() | memberProperties |
| getDeclaredFields() | declaredMemberProperties |
| getMethods() | memberFunctions |
| getDeclaredMethods() | declaredMemberFunctions |
1.取得 Class / KClass
| 功能 | Java | Kotlin |
| 取得 class 物件 | Duck.class | Duck::class(KClass) |
| 動態載入類別 | Class.forName(“Duck”) | Class.forName(“Duck”).kotlin(KClass) |
KClass轉成Java Class
Duck::class.java(Class)
java寫法,取得Class
類別名.class
kotlin 取得KClass
類別名::class
kotlin 取得Java Class
類別名::class.java
2.父類別與介面
| 功能 | Java | Kotlin |
| 父類別 | clazz.getSuperclass() | kClass.supertypes |
| 介面 | clazz.getInterfaces() | kClass.java.interfaces 或 supertypes 過濾 interface |
3.取得欄位(Fields)
| 功能 | Java | Kotlin |
| public 欄位 | clazz.getFields() | kClass.memberProperties |
| 所有欄位(含 private) | clazz.getDeclaredFields() | kClass.declaredMemberProperties |
| 欄位名稱 | field.getName() | property.name |
4.取得方法(Methods)
| 功能 | Java | Kotlin |
| public 方法 | clazz.getMethods() | kClass.memberFunctions |
| 所有方法(含 private) | clazz.getDeclaredMethods() | kClass.declaredMemberFunctions |
| 取得特定方法 | clazz.getDeclaredMethod(“x”) | declaredMemberFunctions.first { it.name == "x" } |
5.建構子(Constructors)
| 功能 | Java | Kotlin |
| public 建構子 | clazz.getConstructors() | kClass.constructors.filter { it.visibility == PUBLIC } |
| 所有建構子(含 private) | clazz.getDeclaredConstructors() | kClass.constructors(KClass 一律包含全部) |
| 取出無參數建構子 | clazz.getDeclaredConstructor() | kClass.constructors.first { it.parameters.isEmpty() } |
| 呼叫建構子 | constructor.newInstance() | constructor.call() |
6.修改存取權限(private → public)
| 功能 | Java | Kotlin |
| 設置 private | 可呼叫 method.setAccessible(true) | method.isAccessible = true |
| 建構子private | constructor.setAccessible(true) | constructor.isAccessible = true |
7.呼叫方法
| 功能 | Java | Kotlin |
| 呼叫 public 方法 | method.invoke(instance) | method.call(instance) |
| 呼叫 private 方法 | method.setAccessible(true) | method.isAccessible = true |
| 呼叫 | method.invoke(instance) | method.call(instance) |
| 呼叫帶參數方法 | method.invoke(obj, a, b) | method.call(obj, a, b) |
8.建立物件
| 功能 | Java | Kotlin |
| 以預設建構子建立 | clazz.newInstance() | kClass.createInstance() |
| 以特定建構子建立 | constructor.newInstance(args…) | constructor.call(args…) |
9.取得屬性與方法的詳細資訊
| 功能 | Java | Kotlin |
| 取得參數型別 | method.getParameterTypes() | function.parameters |
| 取得回傳型別 | method.getReturnType() | function.returnType |
| 欄位型別 | field.getType() | property.returnType |
| 檢查是否是 private | Modifier.isPrivate(method.getModifiers()) | function.visibility |
10.父類別方法 or 屬性
java
clazz.getSuperclass().getDeclaredMethods();
kotlin
val superClass = kClass.supertypes.first().classifier as KClass<*>
superClass.declaredMemberFunctions
反射範例
1
2
3
4
5
6
7
8
9
10
11
12
13
open class Animal {
val species: String = "unknown"
}
interface Flyable
interface Swimable
class Duck : Animal(), Flyable, Swimable {
val name: String = "Donald"
fun quack() {}
private fun secret() {}
}
取得父類別
1
2
3
4
5
6
7
fun main() {
val kClass = Duck::class
val superClass = kClass.supertypes
println("Supertypes:")
superClass.forEach { println(it) }
}
Kotlin 的 supertypes 會列出:
父類別 Animal
介面 Flyable
介面 Swimable
取得介面
1
2
3
4
5
fun main() {
val kClass = Duck::class
println("Interfaces:")
kClass.java.interfaces.forEach { println(it) }
}
取得public屬性
1
2
3
4
5
6
7
8
import kotlin.reflect.full.memberProperties
fun main() {
val kClass = Duck::class
println("Public properties:")
kClass.memberProperties.forEach { println(it) }
}
取得所有屬性
1
2
3
4
5
6
7
8
import kotlin.reflect.full.declaredMemberProperties
fun main() {
val kClass = Duck::class
println("Declared properties (all from this class):")
kClass.declaredMemberProperties.forEach { println(it) }
}
取得public方法
1
2
3
4
5
6
7
8
import kotlin.reflect.full.memberFunctions
fun main() {
val kClass = Duck::class
println("Public methods:")
kClass.memberFunctions.forEach { println(it) }
}
取得所有方法
1
2
3
4
5
6
7
8
import kotlin.reflect.full.declaredMemberFunctions
fun main() {
val kClass = Duck::class
println("Declared methods (all):")
kClass.declaredMemberFunctions.forEach { println(it) }
}
取得父類別所有方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import kotlin.reflect.full.declaredMemberFunctions
open class Animal {
fun speak() {}
private fun secret() {}
}
class Dog : Animal() {
fun bark() {}
}
fun main() {
val kClass = Dog::class
// 子類別
println("Declared methods in Dog:")
kClass.declaredMemberFunctions.forEach { println(it) }
// 父類別
val superKClass = kClass.supertypes.first().classifier as? KClass<*>
println("Declared methods in Animal:")
superKClass?.declaredMemberFunctions?.forEach { println(it) }
}