为什么Kotlin不允许使用原始类型的lateinit?

Kal*_*lja 40 primitive initialization kotlin

在Kotlin语言中,默认情况下,我们必须在引入每个变量时对其进行初始化.为避免这种情况,lateinit可以使用关键字.lateinit在初始化之前引用变量会导致运行时异常.

lateinit但是,不能与原始类型一起使用.为什么会这样?

yol*_*ole 40

对于对象类型,Kotlin使用该null值来标记lateinit属性尚未初始化,并在访问属性时抛出相应的异常.

对于原始类型,没有这样的值,因此无法将属性标记为未初始化并提供lateinit需要提供的诊断.(我们可以尝试使用某种单独的标记,但在通过反射初始化字段时不会更新该标记,这是一个主要的用例lateinit).

因此,lateinit仅支持对象类型的属性.

  • 你能在答案中澄清一下,为什么`lateinit Int`在运行时不能用`Integer`类型表示,它在未初始化时能够保存`null`值? (43认同)
  • 所以,我认为Kotlin将原始类型包装到object(例如int到Int).但是,为什么Int不能保持null,因为它是一个对象?另外,为什么我们不能将参数声明为可空和延迟呢?(var x:Int?) (4认同)
  • @GustavoMaciel但是如果我说`lateinit var int:Int?`,那么我不明白为什么这行不通,因为Kotlin已经用`Integer`表示`Int?`... (3认同)
  • @Yao 出于与 yole 解释的相同原因。基本上,您需要一个未使用的值,可用于标记 var 未初始化的事实。如前所述,原语没有这样的值(原语 var 可以保存的所有值都是有效的)。同样的问题也适用于可空变量:所有值,包括空值,都是有效的(你可以用空值初始化一个可空变量)。因此,没有未使用的值可以将 var 标记为未初始化。 (2认同)
  • @forresthopkinsa因为`lateinit`和`?`冲突。前者说您有一个在初始化后将始终具有某些值的变量,后者说您有一个可能具有或不具有某些值的变量。您不需要`?.`或在`lateinit` var上检查是否为空。 (2认同)

vod*_*dan 9

一个简短的回答是,对于原语,您始终可以将其0用作默认值,并将可空类型null用作默认值。只有不可为空的非原始类型可能需要lateinit绕过类型安全系统。

实际上,在 Kotlin 中不需要初始化一个变量,只要它第一次访问之前有一个值并且可以静态证明。这意味着此代码完全有效:

fun main(args: Array<String>) {
    var x: Int
    val y: Double

    x = 0
    y = x + 0.1

    println("$x, $y") 
}
Run Code Online (Sandbox Code Playgroud)

但是有(罕见的)初始化不能被静态证明的情况。最常见的情况是使用任何形式的依赖注入的类字段:

class Window {
    @Inject lateinit parent: Parent
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为这有点误导。它表明需要 Lateinit 的*唯一*原因是当编译器不够智能来确定属性是否已初始化时向编译器提供提示。另一个完全有效的用例(这对于基元特别有用)是确保如果客户端代码尝试在初始化/计算之前访问一个值,则立即抛出描述性异常,而不是基于某个值默默地做错误的事情。默认值为 0 或 false。 (2认同)