Kotlin数据类:如果我不知道它的名字在编译时如何读取属性的值?
如果只有在运行时才知道属性名称,我怎样才能读取Kotlin数据类实例中的属性值?
你可以通过反射来完成 ,对于数据类和普通数据类都是一样的。
第一个选项只是使用Java反射:
val name = obj.javaClass .getMethod("getName") // to get property called `name` .invoke(obj)
你甚至可以做一个扩展功能:
inline fun <reified T : Any> Any.getThroughReflection(propertyName: String): T? { val getterName = "get" + propertyName.capitalize() return try { javaClass.getMethod(getterName).invoke(this) as? T } catch (e: NoSuchMethodException) { null } }
它称为公共获取者。 要获取私有属性的值,可以使用getDeclaredMethod
和setAccessible
修改此代码。 这也适用于具有相应getter的Java对象(但是它忽略了is
的约定 ,并且has
boolean
getter)。
和用法:
data class Person(val name: String, val employed: Boolean) val p = Person("Jane", true) val name = p.getThroughReflection<String>("name") val employed = p.getThroughReflection<Boolean>("employed") println("$name - $employed") // Jane - true
第二个选项是使用kotlin-reflect
库,你应该单独添加到你的项目中, 这里是它的文档 。 它会让你获得实际的Kotlin属性值,忽略Java getters。
您可以使用javaClass.kotlin
获取实际的Kotlin类令牌,然后从中获取属性:
val name = p.javaClass.kotlin.memberProperties.first { it.name == "name" }.get(p)
这个解决方案只适用于Kotlin类,不适用于Java类,但是如果您需要使用Kotlin类,它将更加可靠:它不依赖于底层的实现。
下面是一个函数,用于从给定属性名称的类的实例中读取属性( 如果找不到属性,则抛出异常,但可以更改该行为 ):
fun <R: Any?> readPropery(instance: Any, propertyName: String): R { val clazz = instance.javaClass.kotlin @Suppress("UNCHECKED_CAST") return clazz.declaredMemberProperties.first { it.name == propertyName }.get(instance) as R }
示例用法:
// some data class data class MyData(val name: String, val age: Int) // and reading property "name" from an instance called "data" val name: String = readPropery(data, "name")
注意: kotlin-reflect依赖是必需的