如何通过reflection来使用Kotlin对象
比方说,我需要通过reflection来设置由字符串给定的Kotlin对象O中的字符串给定的属性A. 如果O是一个class级,我可以做这样的事情(无视它是没有意义的):
fun setValue(ownerClassName: String, fieldName: String, value : Any) { val enclosingClass = Class.forName(ownerClassName).newInstance() val enclosingClassField = enclosingClass.javaClass.getDeclaredField(fieldName) enclosingClassField.isAccessible = true enclosingClassField.set(enclosingClass, value) }
但是如果O是一个对象,我该怎么做呢?
KClass
有一个objectInstance
字段:
Class.forName(ownerClassName).kotlin.objectInstance
这被建成Kotlinreflection。
返回 :对象声明的实例,如果此类不是对象声明,则返回 null。
如果KClass
有一个forName
方法,这将更好,但可惜它还没有 ,所以我们需要取而代之(Java) Class
并将其转换为KClass
。
您可以使用.kotlin
扩展属性从Class
获取KClass
实例。
那么你可以继续你的代码的其余部分。 我把它转换成Kotlin的reflection库:
val kClass = Class.forName(ownerClassName).kotlin val instance = kClass.objectInstance ?: kClass.java.newInstance() // Get the object OR a new instance if it doesn't exist val member = kClass.memberProperties .filterIsInstance>() // Has to be a mutable property, otherwise we can't set it .filter { it.name == fieldName } // Check the name .firstOrNull() member?.setter?.call(instance, value) // Set the property
这是一个工作测试:
object TestObject { var field = 3 } fun setValue(ownerClassName: String, fieldName: String, value: Any) { val kClass = Class.forName(ownerClassName).kotlin val instance = kClass.objectInstance ?: kClass.java.newInstance() val member = kClass.memberProperties.filterIsInstance>() .firstOrNull { it.name == fieldName } member?.setter?.call(instance, value) } fun main(args: Array) { println(TestObject.field) // 3 setValue("some.package.TestObject", "field", 4) println(TestObject.field) // 4 }
object
被转换成一个私有构造函数和一个名为INSTANCE
的静态字段,其中唯一的实例存储在这个类被加载,所以用Class.forName(ownerClassName).newInstance()
与
Class.forName(ownerClassName).getDeclaredField("INSTANCE").get(null)
应该管用。
的Javadoc:
-
Class#forName
-
Class#getDeclaredField
-
Field#get