0

假设我有以下课程:

class ExampleClass: OtherClass {
  lateinit var thing: Thing
  var thingOptional: Thing? = null
  fun exampleFun() {
    val innerThing = thing ?: Thing()
    val innerThing2 = thingOptional ?: Thing()
  }
}

产生以下警告:

Elvis operator (?:) always returns the left operand of non-nullable type Thing

然后是以下运行时异常:

lateinit property thing has not been initialized

因此,在我的理解中,可选可以是一种类型,也可以是任何时候的 null,而lateinit变量可以是 null,直到它被赋予一个值,然后再也不能为 null,并且必须被赋予一个值。但是很明显,语义lateinit略有不同。

那么:lateinit为什么它不是 falsy 的起始值是多少?是否可以以lateinit这种方式使用,作为可选的替代品?如果没有,我该如何创造这种价值?(允许 null 作为起始状态,但随后不可为 null)

4

2 回答 2

3

在执行任何读取之前,您仍然必须手动为lateinit字段分配值,该标志所做的只是减轻了在构造函数中对其进行初始化的需要。后期初始化文档

正如您已经注意到字段没有初始值lateinit- 它在读取时引发异常,但您可以手动检查它是否已使用this::thing.isInitialized.

于 2018-06-02T19:04:11.537 回答
2

所以基本上在 Kotlin 中发生的事情lateinit只是意味着您在声明它时不需要初始化该变量,但您有责任在读取或访问它之前对其进行初始化,否则它将在运行时引发异常。

当您使用依赖注入进行初始化时,它基本上很有用。

所以现在谈论你的错误,

Elvis operator (?:) always returns the left operand of non-nullable type Thing

您之所以遇到上述错误,是因为您lateinit var thing在初始化它之前正在访问它,并且在您的另一个错误中清楚地说明了它,即

lateinit property thing has not been initialized

现在,回答这个问题:

如果没有,我该如何创造这种价值?(允许 null 作为起始状态,但随后不可为 null)

你可以这样做:

  class ExampleClass: OtherClass {
  var thingOptional: Thing? = null
  fun exampleFun() {
    thingOptional = Thing()// thingsOption was null initially but now it is initialized
  }
}

希望对您有所帮助,如果您还有其他疑问,请告诉我。

于 2018-06-02T20:04:39.083 回答