当前位置: 首页 > 知识库问答 >
问题:

Kotlin数据类:如果我在编译时不知道属性的名称,如何读取属性的值?

阴波峻
2023-03-14

如果属性名称仅在运行时已知,如何读取 Kotlin 数据类实例中的属性值?

共有3个答案

赵开诚
2023-03-14

上面的答案对我不起作用,所以我为此创建了一个扩展函数:

@Throws(IllegalAccessException::class, ClassCastException::class)
inline fun <reified T> Any.getField(fieldName: String): T? {
    this::class.memberProperties.forEach { kCallable ->
        if (fieldName == kCallable.name) {
            return kCallable.getter.call(this) as T?
        }
    }
    return null
}

这是一个示例调用

val valueNeeded: String? = yourObject.getField<String>("exampleFieldName")

在应用程序的build.gradle中也包含此属性:

implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
黄弘盛
2023-03-14

您可以通过反射来做到这一点,对于数据类和普通类都是一样的。

第一种选择是使用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
    }
}

它调用公共getter。要获取私有属性的值,您可以使用< code>getDeclaredMethod和< code>setAccessible修改此代码。这也适用于具有相应getter的Java对象(但是它忽略了< code>is和< code > has getter for < code > boolean 的约定)。

用法:

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

您可以使用javaClass.kotlin获取实际的静态编程语言类标记,然后从中获取一个属性:

val name = p.javaClass.kotlin.memberProperties.first { it.name == "name" }.get(p)

此解决方案仅适用于静态编程语言类,而不适用于Java类,但如果您需要使用静态编程语言类,它会更加可靠:它不依赖于底层实现。

姬庆
2023-03-14

这是一个函数,用于从给定属性名称的类实例中读取属性(如果未找到属性则抛出异常,但您可以更改该行为):

import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties

@Suppress("UNCHECKED_CAST")
fun <R> readInstanceProperty(instance: Any, propertyName: String): R {
    val property = instance::class.members
                     // don't cast here to <Any, R>, it would succeed silently 
                     .first { it.name == propertyName } as KProperty1<Any, *> 
    // force a invalid cast exception if incorrect type here
    return property.get(instance) as R  
}
dependencies {
    implementation(kotlin("reflect"))
}
// some data class
data class MyData(val name: String, val age: Int)
val sample = MyData("Fred", 33)

// and reading property "name" from an instance...
val name: String = readInstanceProperty(sample, "name")

// and reading property "age" placing the type on the function call...
val age = readInstanceProperty<Int>(sample, "age")

println(name) // Fred
println(age)  // 33
 类似资料:
  • 我有一节课: 值是唯一的,如何通过其值获取属性的名称? 通过反射,例如:

  • 问题内容: 我正在尝试执行以下操作: 但是我收到以下错误: 有人可以告诉我我在做什么错吗? 问题答案: 鉴于演员表并不会 真正 检查事情,我将使用完全原始的版本: 这似乎有效。完整的例子:

  • 问题内容: 这是我在jQuery中的响应代码: 每个都是形式。 我希望访问javascript中的这两个数据位,如果我事先不知道例如什么,该怎么做? 问题答案: 使用检索键名的完整列表(阵列)。一个polyfill 在这里可用。 您问题的回答格式仅包含一对键值对。然后可以将代码简化为: 如果你没有在列表中感兴趣的话,使用循环 使用 。必须使用最后一种方法,以排除从原型继承的属性。

  • 问题内容: 我要呼吁汇率第三方API,但JSON返回不断变化,如果我申请到的转换,它将返回我:,所以如果我的要求来,它将返回我。 我将不得不使用将返回的结果映射到pojo中,是否有任何可行的方法? 我当前的硬编码解决方法: 问题答案: 是具有值的字段的对象。 否是with键/值对。 两者都是正确的,但是由于before的值是动态的(变化的),因此它是您需要的第二种解释。 因此,请勿要求将JSON转

  • 问题内容: 我想根据属性名称打印属性值,例如 我想做这样的事情 上面的代码给出了一个,我相信这是因为BeatifulSoup使用了name,所以它不能用作关键字参数。 问题答案: 这很简单,请使用以下代码- 如果不清楚,请发表评论。

  • 问题内容: 我有一个用swift编写的CustomViewController类和用Objective C编写的CustomNavigationController类。我试图将CustomNavigationController作为属性添加到我的CustomViewController中。我已经添加到我的桥接头中。 在我的CustomViewController中,我有: 在尝试构建并运行之前没有