为什么 Kotlin 的 null 安全性不能与局部变量初始值设定项一起正常工作?

Why does Kotlin's null safety not work properly with local variable initializers?

请看这段代码:

fun localVarNullSafety1(){
    var number: Double? = 3.0

    val sum = 2.0 + number // does not compile (Type mismatch: inferred type is Double? but Double was expected)
}

fun localVarNullSafety1(){
    var number: Double? = null
    
    number = 3.0

    val sum = 2.0 + number // compiles fine
}

我认为上面的代码由语义相同的函数组成——局部变量不会超出范围,它们对执行线程而言是局部的。在我看来,第一个函数没有理由不编译。

我认为 Kotlin 的智能转换应该考虑变量初始化。

我是否漏掉了一些明显的东西?

这在 KT-13663 中进行了讨论,在撰写本文时它仍然是一个开放的票证。

他们正在考虑更一般的情况(请注意 T?T 的超类型):

 val x: Supertype = Subtype()
 var y: Supertype = Subtype()

并决定在 val 的情况下,x 在此处具有类型 Subtype 没有意义,否则您可以不在其中编写类型注释第一名。

虽然这对 vars 可能有意义,但如果仅对 vars 实施智能转换,则 varsvals 将具有不一致的行为关于他们的类型:

val x: Supertype = Subtype()
var y: Supertype = Subtype()

// inconsistent:
x.someSubtypeStuff() // doesn't work, x is a Supertype
y.someSubtypeStuff() // works, y is smart casted to Subtype

所以他们最终没有为初始化实现智能转换。

由于工单还未开放,此功能很可能会在未来的 Kotlin 版本中实现。它可能只支持 vars,同时支持 vars 和 vals,或者只支持可为 null 的类型。让我们期待最好的结果吧!