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