为什么 Kotlin 编译器需要显式初始化 var 属性?

Why Kotlin compiler requires the explicit initializer of var property?

我无法理解以下 Kotlin 文档:

The initializer, getter and setter are optional. Property type is optional
if it can be inferred from the initializer or from the base class member being overridden.

Examples:
var allByDefault: Int? // error: explicit initializer required, default 
getter and setter implied

为什么编译器在这里需要显式初始化器的唯一解释(至少是我能想到的唯一解释)是 Kotlin 没有属性的默认值。这样对吗?如果是这样,为什么?换句话说:Kotlin 属性和 Java 字段(具有默认值)之间有什么区别不允许我们拥有属性的默认值?

这很简单:在 Java 中,默认值为 0(零)和 null。但在 Kotlin 中,大多数值都是不可空的,所以你不能用 null 初始化它们。对于原始值,可能有一个用零初始化的默认策略,但为了保持一致而没有这样做。但在原始数组中,默认值确实为零。

如果您真的需要初始化语义,请查看 lateinit 属性:https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties.

该机制基本上允许使用 null 初始化一个字段,然后将您从空断言中解放出来。

加法

实际上,Kotlin 在初始化方面非常 聪明。例如有效:

val x: Int

if(something)
    x = 1
else
    x = 2

println(x)

这里kotlinc可以证明x在被使用之前被初始化,所以代码是OK

Kotlin 不会隐含地做任何事情。它不会在没有您的特定指令的情况下转换数字类型,也不会在没有明确说明的情况下设置默认值或初始化值。这是一种设计选择,旨在消除在典型 Java 程序中发现的常见错误。如果您忘记初始化它,或者您是否打算使用默认值,编译器并不清楚。因为不清楚,所以不好。因此可能会导致错误。

Kotlin 的设计选择有助于消除由于编译器无法帮助确定是否存在错误的代码而导致的错误。它在语言上具有哲学性和一致性。

Kotlin 在使用前需要初始化。对于成员,这意味着在构造函数和初始值设定项完成时,它必须有一个值。 var 上的 lateinit 修饰符允许在编译时忽略它,尽管在运行时会在您访问变量时进行检查。对于局部变量,任何代码分支都必须在访问前初始化值。例如:

fun stateFromAbbreviation(abbreviation: String?): String {
    val state: String

    if (abbreviation == null) {
        state = DEFAULT_STATE
    }
    else {
        state = stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation")
    }

    return state
}

这里局部变量可以在if语句中初始化,假设所有分支都初始化该值。但实际上,使用 if 作为表达式,这段代码会更加地道,例如:

fun stateFromAbbreviation(abbreviation: String?): String {
    return if (abbreviation == null) {
        DEFAULT_STATE
    }
    else {
        stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation")
    }
}