Kotlin的逻辑'和'不会短路?

Kur*_*eek 3 kotlin

我在http://kotlinlang.org/docs/reference/null-safety.html#checking-for-null-in-conditions上跟随Kotlin的文档,并尝试调整此示例,

val b = "Kotlin"
if (b != null && b.length > 0) {
    print("String of length ${b.length}")
} else {
    print("Empty string")
}
Run Code Online (Sandbox Code Playgroud)

在哪种情况下b = null.在IntelliJ Idea Kotlin项目中,我有app.kt一个main()函数定义为:

fun main() {
    val b = null
    if (b != null && b.length > 0) {
        print("String of length ${b.length}")
    } else {
        print("Empty string")
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我运行它时,我得到两个编译错误:

Information:Kotlin: kotlinc-jvm 1.3.20 (JRE 11+28)
Information:2019-02-02 15:07 - Compilation completed with 2 errors and 0 warnings in 1 s 921 ms
/Users/kurtpeek/IdeaProjects/HelloWorld/src/app.kt
Error:(3, 24) Kotlin: Unresolved reference: length
Error:(4, 37) Kotlin: Unresolved reference: length
Run Code Online (Sandbox Code Playgroud)

据我所知,编译器评估b.length,即使第一个条件,b != nullfalse.这让我感到惊讶,因为我认为第一次检查是在需要时"短路"布尔表达式并调用b.length"安全".

例如,在Python中,您可以这样做:

In [1]: "foo" == "bar" and what.the.heck
Out[1]: False
Run Code Online (Sandbox Code Playgroud)

即使what没有定义也可以工作,因为and"停止" "foo"不等于"bar".

这确实是Kotlin的作品吗?似乎缺少Python的"短路"功能将是一个限制.

Tod*_*odd 9

Kotlin的&&运算符将短路(就像Java一样)但仅在运行时.您遇到的是编译时错误.特别是在将Kotlin(或Java)与Python进行比较时要记住的最大区别是Kotlin和Java是静态类型的并且具有编译阶段.因此,如果类型不匹配,您将收到编译错误.

让我们一次看看这些......

val b = "Kotlin"
if (b != null && b.length > 0) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Kotlin将正确地推断出这b是类型String,因为你明确地将它设置为String("Kotlin").我们在这里应该注意,String类型不能包含null.知道这一点,b != null你的if陈述部分是不必要的.但是,在评估之后(总是如此),它将进行评估,b.length因为它b是a String,因此具有length属性.这个例子应该编译好(我没有测试它).

接下来......

val b = null
if (b != null && b.length > 0) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这段代码不会编译,让我们来看看为什么......

此代码看起来非常相似,但有一个巨大的区别.在这种情况下,因为你刚才设置bnull,科特林是要推断bNothing?.它没有关于你想成为什么类型的信息b,你已经将它设置为null(因为它是a val,它将永远null).由于bnull,它使b空.

所以,考虑到这一点,当我们编译时b != null,总是会失败,因为b不可能不是null.可是等等!我们现在正在编译......当我们遇到b.lengthKotlin时会抛出编译错误,因为Nothing?没有length属性!

从本质上讲,通过设置bnull,而不是提供一种暗示,科特林需要它可以唯一的路径来推断类型- Nothing?.

  • 这是有道理的,我设置了`val b: String? = null` 使 `b` 成为可为 null 的字符串(而不是 `Any?`),并且该示例有效。 (2认同)