Kotlin:如果 String 为 null 并且使用了双 bang(!!) 运算符,为什么它会给出长度函数的编译错误?

Kotlin : if String is null and double bang(!!) operator is used, why does it give compile error for length function?

示例:

fun main(){
    var userInput: String?
    //userInput = null
    userInput = "asbdef"
    var inputLength:Int? = userInput!!.length
    println("Length of the string is :"+inputLength)
}

输出: 字符串的长度是:6

fun main(){
    var userInput: String?
    userInput = null
    //userInput = "asbdef"
    var inputLength:Int? = userInput!!.length
    println("Length of the string is :"+inputLength)
}

输出: 未解决的参考:长度

我想知道为什么会报编译错误?

如果我只是用 (?) 替换 (!!) 运算符,它编译得很好,但打印输出为 null。

PS:我是 Kotlin 的新手

如果左侧的计算结果为 null,则 ?. 运算符 short-circuits。所以 nullVariable?.length 的结果是 null.length 永远不会被评估。你的第一个例子有效地做了:

println("Length of the string is :" + null)

!! 运算符表示“如果左侧为空,则抛出 NullPointerException。否则,我们知道右侧不为空”。如果稍微更改第二个示例,您可以看到这一点:

val userInput: String? = null
val inputLength:Int = userInput!!.length // throws NullPointerException

但是,我不确定你为什么会得到 Unresolved reference: length。当您将 null 直接分配给 userInput 时,编译器似乎正在做一些优化,而不是将其编译为在运行时抛出 NPE 的 String?,它知道该值是在编译时只有 null(不是 String?),因此不能有 length 属性 因为 null 不是引用。

您可以通过函数调用添加一个抽象层来强制它给您 NullPointerException

fun main(){
    var userInput: String? = "foo"
    userInput = alwaysNull()
    val inputLength:Int = userInput!!.length // NullPointerException
}

fun alwaysNull(): String? = null

我在 Null Safety 文档中没有看到任何关于在一行中初始化/通过函数调用与将 null 直接分配给 var 之间的行为差​​异的内容,那是什么Unresolved reference 背后发生的事情只是一个猜测。