【问题标题】:Listing all the properties in a Kotlin class excluding the ones with custom getters列出 Kotlin 类中的所有属性,不包括具有自定义 getter 的属性
【发布时间】:2021-05-28 14:31:24
【问题描述】:

有什么简单的方法可以列出一个类中的所有属性,不包括带有自定义 getter 的属性?

例如在这种情况下:

class Person(val name: String, val age: Int) {

    val signature: String get() = "$name - $age"
    
    val uuid = UUID.randomUUID()
}

我想找:[ Person::name, Person::age, Person::uuid ]

【问题讨论】:

  • 通过查看生成的字节码,我认为没有什么可以区分生成的和自定义的 getter。幸运的是,Kotlin 编译器将元数据附加到生成的字节码中,并且很可能存在此类信息。元数据是二进制的,所以我没有自己检查,但你可以阅读它:kotlinx-metadatalib。在源代码中,我看到如下标志:IS_SYNTHESIZEDIS_DECLARATION 用于函数、HAS_GETTER 用于道具等,所以也许其中一个会有所帮助。
  • 为什么要这样做?我不禁想知道是否有更好的方法而不使用反射。 (反射是一种高级工具,但它速度慢、脆弱、不安全、丑陋,并且会阻止许多编译时检查。  框架、插件和注释处理器等特殊情况需要它,但 IME 通常很少适用应用程序代码,所以有点代码味道。脚本和其他动态语言中常见的一些模式不能很好地转换为静态语言,例如 Java 和 Kotlin,它们通常有更好的设计。)
  • @gidds 很难准确解释我为什么需要这个。我在单元测试中有一个非常狭窄的用例。我写了一些custom equality checking utility,这在某些情况下非常有用,可以在比较具有大量属性的大型类时避免大量样板代码。我想用自定义 getter 过滤掉属性。

标签: kotlin reflection kotlin-reflect


【解决方案1】:

只有 getter 的属性没有 JVM 支持字段。因此,您可以获取所有属性并排除那些没有字段的属性。

// All properties
Person::class.declaredMemberProperties.forEach {
    println(it.name)
}
println()

// All fields
Person::class.java.declaredFields.forEach {
    println(it.name)
}
println()

您会注意到第二组中缺少signature

【讨论】:

    猜你喜欢
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-08
    • 2017-04-27
    相关资源
    最近更新 更多