Kotlin反思地调用getter/setter

kli*_*ron 5 reflection kotlin

这里是Kotlin的初学者.

我尝试通过程序中的反射来创建和填充对象.我在纯kotlin中找不到相同的功能,所以我的解决方案类似于下面的代码工作正常,但需要使用像脏java.lang.String::class.java和类似的脏引用,可以理解,似乎不喜欢这样.我有什么比这更简单的方法吗?

val jclass = myObject::class.java 
val setters = jclass.declaredMethods.filter { it.name.startsWith("set") }
for (s in setters) {
    val paramType = s.parameterTypes.first()
    val data = when(paramType) {
        java.lang.Integer::class.java -> foo
        java.lang.Double::class.java -> bar
        java.lang.String::class.java -> baz
    }
    s.invoke(myObject, data)
}
Run Code Online (Sandbox Code Playgroud)

hot*_*key 11

您可以使用Kotlin反射,它需要您kotlin-reflect作为项目的依赖项添加.

在这里你可以找到kotlin-reflect Kotlin 1.0.5,或者如果你使用不同的Kotlin版本,可以选择另一个版本.

之后,您可以按如下方式重写代码:

val properties = myObject.javaClass.kotlin.memberProperties
for (p in properties.filterIsInstance<KMutableProperty<*>>()) {
    val data = when (p.returnType.javaType) {
        Int::class.javaPrimitiveType,
        Int::class.javaObjectType -> foo
        Double::class.javaPrimitiveType,
        Double::class.javaObjectType -> bar
        String::class.java -> baz
        else -> null
    }
    if (data != null)
        p.setter.call(myObject, data)
}
Run Code Online (Sandbox Code Playgroud)

一些细节:

  • 尽管使用科特林反射,这种方法与Java类作品,以及,各自的领域和存取会被视为属性,描述在这里.

  • 就像Java反射一样,memberProperties返回public此类型的属性及其所有超类型.要获取在类型中声明的所有属性(包括private那些属性,而不是来自超类型的属性),请declaredMemberProperties改用.

  • .filterIsInstance<KMutableProperty<*>只返回可变属性,以便您以后可以使用它们p.setter.如果需要迭代所有属性的getter,请将其删除.

  • when块,我比较p.returnType.javaTypeInt::class.javaPrimitiveTypeInt::class.javaObjectType,因为什么Int在科特林可以映射到Java的两种intjava.lang.Integer根据其使用情况.在Kotlin 1.1中,它足以检查p.returnType.classifier == Int::class.