【问题标题】:How to hide Kotlin's lateinit var backing field from Java?如何从 Java 中隐藏 Kotlin 的 lateinit var 支持字段?
【发布时间】:2017-03-15 11:23:07
【问题描述】:

在 Kotlin 中,假设我有课:

class MyKotlinClass {
    lateinit var field: String
}

根据docs

后期初始化属性也作为字段公开。该字段的可见性将与 lateinit 属性设置器的可见性相同。

我可以在 java 代码中使用myKotlinClass.fieldmyKotlinClass.getField()。我想禁用字段访问并仅通过 gettersetter 进行访问。

我怎样才能做到这一点并保持 lateinit 修饰符?

【问题讨论】:

    标签: java kotlin kotlin-lateinit


    【解决方案1】:

    您可以使用 @JvmSynthetic 来隐藏 Java(而不是 Kotlin)的声明。只是annotate the backing field的属性:

    @field:JvmSynthetic
    lateinit var field: String
    

    虽然该字段将在字节码中保留public,但它也将具有synthetic 修饰符,这会阻止它在Java 源代码中使用。但是,该字段似乎仍然可以在运行时通过反射访问。

    另请参阅:另一个question about @JvmSynthetic(虽然那里没有明确的答案)。

    【讨论】:

    • 谢谢。这正是我所需要的。
    • 我用 Kotlin 1.0.6 检查了生成的字节码,backing 字段仍然是公开的
    • @voddan,但它现在应该有 synthetic 修饰符,是吗?有了这个修饰符,它在 Java 源代码中的用法应该会失效。
    • @voddan,像这样:public synthetic Ljava/lang/String; s。或者你有没有找到任何方法从 Java 中引用该字段?
    • @hotkey 该字段上似乎有ACC_SYNTHETIC。让我检查一下我是否可以从 Java 访问它
    【解决方案2】:

    这个问题的经典解决方案是使用property delegation

    import kotlin.properties.Delegates
    
    class MyKotlinClass {
        var field: String by Delegates.notNull()
    }
    

    此代码完全符合您在问题中的要求

    【讨论】:

    【解决方案3】:

    lateinit 字段的可见性来源于对应属性的 setter 的可见性,因此另一种选择是具有非公共 setter 的属性:

    lateinit var field: String
        private set
    

    这种方法的缺点是 setter 本身在类之外变得不可访问。

    【讨论】:

      猜你喜欢
      • 2018-05-12
      • 1970-01-01
      • 2013-05-06
      • 2016-07-22
      • 2022-12-15
      • 1970-01-01
      • 2015-05-12
      • 2020-08-08
      • 2012-05-17
      相关资源
      最近更新 更多