我如何通过反射在Kotlin中设置伴随对象的属性?

当我有一个伴侣对象的类,是否有可能使用反射设置此伴随对象的属性? 我可以用普通的属性来做,但是在伴侣对象上失败:

import kotlin.reflect.KMutableProperty import kotlin.reflect.full.companionObject import kotlin.reflect.full.memberProperties class WithProperty { lateinit var prop: String companion object { lateinit var companionProp: String } fun test() = "$companionProp $prop" } fun main(args: Array<String>) { val obj = WithProperty() val prop = obj::class.memberProperties.filter { it.name == "prop" }.first() if (prop is KMutableProperty<*>) { prop.setter.call(obj, "world") } val companion = obj::class.companionObject if (companion != null) { val companionProp = companion.memberProperties.filter { it.name == "companionProp" }.first() if (companionProp is KMutableProperty<*>) { companionProp.setter.call(companionProp, "hello") // <-- what must go here as first argument? } } println(obj.test()) } 

调用setter的正常属性,因为它应该,但是当我打电话companionProp.setter.call(companionProp, "hello")我得到

线程“main”中的异常java.lang.IllegalArgumentException:object不是声明类的实例

我必须通过什么作为第一个参数call()才能成功?

编辑:我写companionProp作为第一个参数,但是这肯定是错误的,我实际上尝试与companion对象,但是这是行不通的。

对象不是声明类的实例

就像在Java中一样,当调用反射方法时,您需要传递对象本身作为第一个参数。

call的第一个参数应该是伴随对象,因为这是您正试图修改其属性的对象。

您正在传递伴侣的类对象,而不是伴随对象本身。

伴侣对象可以通过ClassName.Companion访问,也可以通过KClass#companionObjectInstance进一步反射。

 companionProp.setter.call(WithProperty.Companion, "hello") companionProp.setter.call(obj::class.companionObjectInstance, "hello") companionProp.setter.call(WithProperty::class.companionObjectInstance, "hello") 

运行时,这两种变体都按打算打印hello world

请记住,如果伴随对象不存在, Foo.Companion将导致编译错误,而反射变体将返回null

第一个参数是声明类的实例。

您传递KProperty实例companionProp而不是伴随对象实例。 但是,您可以使用KClass.companionObjectInstance获取compantion实例。 例如:

 //a non-static property having a receiver, so it should be a KMutableProperty1 here // v if (companionProp is KMutableProperty1<*, *>) { // get the companion object instance ---v companionProp.setter.call(obj::class.companionObjectInstance, "hello") }