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

时间:2015-11-14 18:35:32

标签: kotlin

我无法理解以下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字段(具有默认值)之间有什么区别,它们不允许我们拥有属性的默认值?

2 个答案:

答案 0 :(得分:12)

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

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

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

<强> ADDITION

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

val x: Int

if(something)
    x = 1
else
    x = 2

println(x)

此处kotlinc可能会证明{<1}}在使用之前正在初始化,所以代码没问题

答案 1 :(得分:1)

Kotlin没有暗中做任何事情。没有您的特定指令,它不会转换数字类型,也不会在没有显式的情况下设置默认值或初始化值。这是消除典型Java程序中常见错误的设计选择。如果您忘记初始化它或者您打算使用默认值,则编译器不清楚。因为它不清楚,所以很糟糕。因此可能导致错误。

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

Kotlin在使用前需要初始化。对于那些在构造函数和初始化程序完成时表示的成员,它必须具有值。 lateinit上的var修饰符允许在编译时忽略它,尽管在运行时检查是在访问变量时完成的。对于局部变量,任何代码分支都必须在访问之前初始化该值。例如:

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")
    }
}