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 } } 

它称为公共获取者。 要获取私有属性的值,可以使用getDeclaredMethodsetAccessible修改此代码。 这也适用于具有相应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依赖是必需的