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) }
}

results matching ""

    No results matching ""