如何使用Kotlin.reflect API为Kotlin object类设置属性值?
解决Kotlin反射给object类属性赋值的参数异常问题
问题原因
Kotlin的object是单例实现,它的成员属性在反射体系里属于无接收者的属性,对应反射类型是KMutableProperty0;而普通类的属性是有接收者的属性,对应KMutableProperty1。你之前的代码把object的属性强转成了KMutableProperty1,调用set(receiver, value)时,相当于给只需要1个参数的方法传了2个参数,自然触发参数数量不匹配的异常。
解决方案
反射时需要区分属性类型,分别处理普通类和object类的赋值逻辑:
- 普通类属性(
KMutableProperty1):调用set(receiver, value),传入实例和属性值 object类属性(KMutableProperty0):直接调用set(value),无需传入接收者实例
修正后的完整代码
import kotlin.reflect.KClass import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty1 import kotlin.reflect.full.declaredMemberProperties import kotlin.reflect.jvm.isAccessible fun main() { test(RegularClass::class, RegularClass()) // 正常输出 "Hello world!" test(ObjectClass::class, ObjectClass) // 现在可正确赋值并输出 } private fun test(kClass: KClass<out Greeter>, receiver: Greeter?) { val property = kClass.declaredMemberProperties.first { it.name == "variable" } property.isAccessible = true when (property) { is KMutableProperty1<*, *> -> { @Suppress("UNCHECKED_CAST") (property as KMutableProperty1<Any?, Any?>).set(receiver, "Hello world!") } is KMutableProperty0<*> -> { @Suppress("UNCHECKED_CAST") (property as KMutableProperty0<Any?>).set("Hello world!") } } receiver?.helloWorld() } interface Greeter { fun helloWorld() } class RegularClass: Greeter { private var variable: String = "Wrong value" override fun helloWorld() { println(variable) } } object ObjectClass: Greeter { private var variable: String = "Wrong value" override fun helloWorld() { println(variable) } }
额外说明
- 之所以没抛出
OperationNotSupported异常,是因为object的属性本身支持修改,只是你的调用方式错误,JVM抛出参数不匹配异常是合理的。 - 代码里的
@Suppress("UNCHECKED_CAST")是为了消除类型转换警告,你也可以根据实际场景做更严格的类型校验。
内容的提问来源于stack exchange,提问作者Marcoral
相关产品推荐
相关产品推荐

