Kotlin 反射 #

一、反射概述 #

反射允许在运行时检查和操作类、函数、属性等。

1.1 添加依赖 #

kotlin
// build.gradle.kts
dependencies {
    implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.22")
}

二、KClass #

2.1 获取 KClass #

kotlin
// 使用 ::class
val stringClass = String::class

// 使用 javaClass
val obj = "Hello"
val klass = obj::class

// 使用 Class 转换
val javaClass = String::class.java
val kotlinClass = javaClass.kotlin

2.2 类信息 #

kotlin
class Person(val name: String, var age: Int)

fun main() {
    val klass = Person::class
    
    println(klass.simpleName)      // Person
    println(klass.qualifiedName)   // com.example.Person
    println(klass.isData)          // false
    println(klass.isSealed)        // false
    println(klass.isAbstract)      // false
}

2.3 创建实例 #

kotlin
class Person(val name: String, var age: Int)

fun main() {
    val klass = Person::class
    
    // 使用主构造函数
    val person = klass.primaryConstructor?.call("Kotlin", 10)
    
    // 使用 createInstance(需要无参构造函数)
    // val instance = klass.createInstance()
}

三、KFunction #

3.1 获取函数引用 #

kotlin
class Person(val name: String) {
    fun greet() = "Hello, $name"
    
    fun greetWith(greeting: String) = "$greeting, $name"
}

fun main() {
    val person = Person("Kotlin")
    
    // 成员函数引用
    val greet = Person::greet
    println(greet.call(person))  // "Hello, Kotlin"
    
    // 绑定函数引用
    val boundGreet = person::greet
    println(boundGreet())  // "Hello, Kotlin"
}

3.2 函数信息 #

kotlin
fun add(a: Int, b: Int): Int = a + b

fun main() {
    val func = ::add
    
    println(func.name)           // add
    println(func.parameters)     // [a, b]
    println(func.returnType)     // kotlin.Int
}

3.3 调用函数 #

kotlin
fun add(a: Int, b: Int): Int = a + b

fun main() {
    val func = ::add
    
    // 直接调用
    val result1 = func.call(1, 2)  // 3
    
    // 按名称调用
    val result2 = func.callBy(mapOf(
        func.parameters[0] to 1,
        func.parameters[1] to 2
    ))
}

四、KProperty #

4.1 获取属性引用 #

kotlin
class Person(var name: String, val age: Int)

fun main() {
    val person = Person("Kotlin", 10)
    
    // 属性引用
    val nameProp = Person::name
    println(nameProp.get(person))  // Kotlin
    
    // 绑定属性引用
    val boundName = person::name
    println(boundName.get())  // Kotlin
    
    // 修改属性
    nameProp.set(person, "Java")
    println(person.name)  // Java
}

4.2 属性信息 #

kotlin
class Person(val name: String, var age: Int)

fun main() {
    val klass = Person::class
    
    // 获取所有属性
    val properties = klass.memberProperties
    
    properties.forEach { prop ->
        println("${prop.name}: ${prop.returnType}")
        println("Is mutable: ${prop is KMutableProperty1}")
    }
}

4.3 延迟属性 #

kotlin
class Example {
    val lazyValue: String by lazy { "Lazy" }
}

fun main() {
    val prop = Example::lazyValue
    
    // 检查是否是延迟属性
    val delegate = prop.getDelegate(Example())
    println(delegate is Lazy<*>)  // true
}

五、遍历成员 #

5.1 遍历函数 #

kotlin
class Service {
    fun method1() { }
    fun method2(param: String) { }
    private fun privateMethod() { }
}

fun main() {
    val klass = Service::class
    
    // 所有公开成员函数
    klass.memberFunctions.forEach { func ->
        println(func.name)
    }
    
    // 所有声明的函数(包括私有)
    klass.declaredMemberFunctions.forEach { func ->
        println(func.name)
    }
}

5.2 遍历属性 #

kotlin
class User(
    val id: Int,
    var name: String,
    private var password: String
)

fun main() {
    val klass = User::class
    
    klass.memberProperties.forEach { prop ->
        println("${prop.name}: ${prop.returnType}")
    }
}

5.3 遍历构造函数 #

kotlin
class Person(val name: String) {
    constructor(name: String, age: Int) : this(name)
}

fun main() {
    val klass = Person::class
    
    // 主构造函数
    println(klass.primaryConstructor)
    
    // 所有构造函数
    klass.constructors.forEach { ctor ->
        println(ctor.parameters)
    }
}

六、注解处理 #

6.1 获取类注解 #

kotlin
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Table(val name: String)

@Table("users")
class User

fun main() {
    val annotation = User::class.findAnnotation<Table>()
    println(annotation?.name)  // users
}

6.2 获取属性注解 #

kotlin
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Column(val name: String)

class User(
    @Column("user_name")
    val name: String
)

fun main() {
    val prop = User::class.memberProperties.find { it.name == "name" }
    val annotation = prop?.findAnnotation<Column>()
    println(annotation?.name)  // user_name
}

七、实战示例 #

7.1 对象复制 #

kotlin
inline fun <reified T : Any> T.copyFrom(source: T): T {
    val klass = T::class
    val constructor = klass.primaryConstructor ?: return this
    
    val args = constructor.parameters.associateWith { param ->
        val prop = klass.memberProperties.find { it.name == param.name }
        prop?.get(source) ?: param.defaultValue?.invoke()
    }
    
    return constructor.callBy(args)
}

7.2 属性映射 #

kotlin
fun <T : Any> T.toMap(): Map<String, Any?> {
    return this::class.memberProperties.associate { prop ->
        prop.name to prop.getter.call(this)
    }
}

fun <T : Any> Map<String, Any?>.toObject(klass: KClass<T>): T {
    val constructor = klass.primaryConstructor!!
    val args = constructor.parameters.associateWith { param ->
        this[param.name]
    }
    return constructor.callBy(args)
}

7.3 简单 ORM #

kotlin
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Entity(val tableName: String = "")

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Id

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Column(val name: String = "")

@Entity("users")
data class User(
    @Id
    @Column("id")
    val id: Long,
    
    @Column("name")
    val name: String
)

fun <T : Any> insert(entity: T) {
    val klass = entity::class
    val tableName = klass.findAnnotation<Entity>()?.tableName ?: klass.simpleName!!
    
    val columns = klass.memberProperties
        .filter { it.findAnnotation<Id>() == null }
        .map { prop ->
            val columnName = prop.findAnnotation<Column>()?.name ?: prop.name
            columnName to prop.getter.call(entity)
        }
    
    val sql = "INSERT INTO $tableName (${columns.joinToString { it.first }}) VALUES (${columns.joinToString { "?" }})"
    println(sql)
}

八、最佳实践 #

8.1 缓存反射结果 #

kotlin
val propertyCache = mutableMapOf<KClass<*>, Collection<KProperty1<*, *>>>()

fun <T : Any> getProperties(klass: KClass<T>): Collection<KProperty1<T, *>> {
    return propertyCache.getOrPut(klass) {
        klass.memberProperties
    } as Collection<KProperty1<T, *>>
}

8.2 使用 reified 简化 #

kotlin
inline fun <reified T : Any> create(): T {
    return T::class.createInstance()
}

8.3 处理异常 #

kotlin
fun safeCall(func: KFunction<*>, vararg args: Any?): Result<Any?> {
    return try {
        Result.success(func.call(*args))
    } catch (e: Exception) {
        Result.failure(e)
    }
}

九、总结 #

反射要点:

概念 说明
KClass 类反射
KFunction 函数反射
KProperty 属性反射
call 调用函数
get/set 访问属性

下一步,让我们学习 委托

最后更新:2026-03-27