【问题标题】:isInitialized - Backing field of lateinit var is not accessible at this pointisInitialized - lateinit var 的支持字段此时不可访问
【发布时间】:2018-05-12 22:33:04
【问题描述】:

我正在尝试检查 lateinit 属性是否已初始化。
在 Kotlin 1.2 中,我们现在有了 isInitialized 方法。当我在声明了 lateinit 属性的类中这样做时,它会起作用。 但是当我尝试从另一个类调用它时,我收到以下警告:

此时无法访问“lateinit var foo: Bar”的支持字段

我的模型类(比如Person)是用 Java 编写的
另外两个类(比如Test1Test2)是用 Kotlin 编写的

例子:

class Test1 {
    lateinit var person: Person

    fun method() {
        if (::person.isInitialized) {
            // This works
        }
    }
}

-

class Test2 {
    lateinit var test1: Test1

    fun method() {
        if (test1::person.isInitialized) {
            // Error
        }
    }
}

有没有机会让这个工作?

我目前的解决方法是在 Test1 中创建一个从 person 属性返回 isInitialized 的方法。

fun isPersonInitialized(): Boolean = ::person.isInitialized

//in Test2:
if (test1.isPersonInitialized()) {
    // Works
}

【问题讨论】:

  • 我不知道答案。但是为什么你使用isInitialized 而不是可空的呢? lateinit show 总是在使用对象之前被初始化。
  • @Eledgy 您的代码无法编译。您不能将 if 表达式直接放在类主体中。我想你忘了把它包装在一个 init 块中。我知道,这并不能解决您的初始问题。
  • @Joshua 我有一个人可能还没有被初始化的情况
  • @WilliMentzel 只是一个例子,我已经把代码放在了一个方法中
  • @ElegyD 然后,您应该使用Person?。如果您滥用 lateinit,则每次访问人员时都需要一个 if,这会使您返回 Java 并进行空检查。

标签: java kotlin kotlin-lateinit


【解决方案1】:

accepted answer 描述的约束的一个非常简单的解决方法如下:

class LateClass {
    lateinit var thing: Thing
    fun isThingInitialized() = ::thing.isInitialized
}

class Client {
    val lateClass = LateClass()
    ... things happen ...
    if (lateClass.isThingInitialized() {
        // do stuff with lateClass.thing, safely
    }
}

【讨论】:

  • 非常漂亮和优雅。转换为属性.. val isThingInitialized: Boolean = ::thing.isInitialized
  • @TejasviHegde 不会在创建时将 isThingInitialized 设置为 false,并且考虑到它是不可变的,一旦事物被初始化就永远不会更新为 true?
  • @ThomasSunderland isThingInitialized 不是一成不变的,它是一个函数。
  • val isThingInitialized: Boolean = ::thing.isInitialized 将始终为 false,因为仅预先计算一次。您可以在此解决方案中创建一个函数,或创建一个惰性字段:val isThingInitialized: Boolean by lazy { ::thing.isInitialized }
  • @TejasviHegde 使用属性只有在设置 getter 后才能成功。
【解决方案2】:

根据docs

此检查仅适用于词法可访问的属性,即在同一类型或外部类型之一中声明,或在同一文件的顶层声明。

这就是为什么你不能在主函数中检查它的原因。

【讨论】:

  • 在 kotlin v1.3.+ 中仍应考虑这一点 :)
【解决方案3】:

我作为 Kotlin 属性的版本。

class LateClass {
    lateinit var thing: Thing
    val isThingInitialized get() = this::thing.isInitialized 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-12
    • 2020-12-12
    相关资源
    最近更新 更多