首页 > 解决方案 > 收藏> 如何获取属性实例

问题描述

我目前正在使用反射在运行时使用该class.memberProperties函数检查元素。的类型properties是,所以我通过检查名称是否等于“nameIWant”来collection<KProperty1<I, *>>遍历每个对象以找到我想要的对象,尽管我更希望能够通过使用上的方法,这样我就可以进行检查,例如:KPropertyKProperty.get()property

if (property.get(receiver) is ClassIWant) {
  //Do something
}

我的代码如下所示:

val properties = request.payload::class.memberProperties
  properties.forEach { property ->
    run {
      if (property.name.equals("nameIWant")) {

      }
    }
  }

到目前为止,我一直在尝试.get()在 type 上使用该方法,KProperty1但它需要一个receivertype参数Nothing。我无法弄清楚我需要传递什么才能调用该.get()方法并获取该属性的特定实例。我还检查了这里的文档:https ://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-property1/index.html但它并没有真正帮助。

标签: kotlin

解决方案


如果要获取属性的值,请将类转换为不变类型。

instance::class.memberProperties.first() // returns KProperty1<out Instance, *>
(instance::class as KClass<Instance>).memberProperties.first() // returns KProperty1<Instance, *>

如果你KClass<Instance>KClass<*>,使用Anyas Instance

为什么KProperty.callNothing作为接收者?因为instance::classreturn KClass<out Instance>,它将协变类型参数传播到属性,它变成KProperty<out Instance, *>,这将可能的方法接收器缩小到 Instance 的任何子类型,但是因为我们不知道哪个,我们不能安全地提供 Instance 的任何实例,因为由方差规则显示,这里将泛型类型参数限制为Nothing,这意味着根本不可能调用该方法。

为什么::class设计为协变的?以保证安全。这一直是一个争论不休的问题,因为它似乎有些不合逻辑。

如果您想知道属性可以返回的值的类型,请使用

property.returnType

它返回一个 KType,它是 Kotlin 版本的 Java 类型,它是一个更通用的类概念(它是类型的实现之一)。

如果您需要将 KType '转换'为 KClass,则需要执行与将 Type 转换为 Class 相同的操作,即获取类型的原始类型。原始类型是剥离了任何通用信息的类型,是的,是一种擦除类型。这样做的方法(似乎)更复杂(涉及处理每个可能的 KType/Type 实现),我建议单独检查这个问题的答案。

您将能够使用以下方法重用 Java 实现(您肯定会自己找到):

kType.javaType.covertJavaTypeToJavaClass().kotlin  // returns KClass<*>

更正您的问题。如果您希望收到正确的答案,我建议使用正确的术语: *I在您的问题中是方法接收器的类型,而不是属性的值 *collection不是类型,Collection is *property is ClassIWant是不明确property.type的,因为属性中的值的类型和property::class只是属性实现,is也是一个instanceof检查,但是在反射中,您需要使用KClass.isSubclassOf,或者在 Java 中称为type.isAssignableFrom(注意调用顺序),这使得您的条件成为ClassIWant.isSuperclassOf(property.type.getRawType()) *instance of the property属性具有值,而不是实例。只有类有实例。实例是值,值是(某个类的)实例,但您仍然必须说instance representing the value of the property


推荐阅读