我按照Kotlin在http://kotlinlang.org/docs/reference/null-safety.html#checking-for-null-in-conditions上的文档进行操作,并尝试改编此示例,

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

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

但是,运行此命令时,出现两个编译错误:
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

我了解即使第一个条件b.lengthb != null,编译器仍在评估false。这让我感到惊讶,因为我认为第一个检查是必要时“短路” bool 表达式,然后调用b.length“safe”。

例如,在Python中,您可以执行以下操作:
In [1]: "foo" == "bar" and what.the.heck
Out[1]: False

即使未定义what,该方法仍然有效,因为and不等于"foo",所以"bar"会“停止”。

这确实是 Kotlin 的工作方式吗?似乎缺少Python的“短路”功能将是一个限制。

最佳答案

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

让我们一次浏览一下这些内容...

val b = "Kotlin"
if (b != null && b.length > 0) {
    ...
}

在这种情况下,Kotlin将正确地推断bString类型,因为您已将其明确设置为String(“Kotlin”)。在这里我们应该注意,String类型永远不能包含null。知道这一点,就不需要b != null语句的if部分。但是,在对它进行评估(始终为true)之后,它将评估b.length,因为bString,因此具有length属性。这个例子应该可以编译(我没有测试)。

接下来...
val b = null
if (b != null && b.length > 0) {
    ...
}

这段代码不会编译,让我们回顾一下原因...

这段代码看起来确实很相似,但有很大的不同。在这种情况下,因为您只是将b设置为null,所以Kotlin会推断bNothing?。它没有有关您想要b的类型的信息,并且已将其设置为null(并且由于它是val,因此始终为null)。因为bnull,所以它使b可为空。

因此,鉴于此,当我们编译b != null时,它将总是失败,因为b永远不可能是不是null的东西。可是等等!我们正在编译...当我们遇到b.length时,由于Nothing?没有length属性,因此Kotlin将引发编译错误!

本质上,通过将b设置为null而不提供类型提示,Kotlin将采用唯一的路径来推断类型-Nothing?

关于Kotlin的逻辑 'and'不会短路吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54498548/

10-16 22:53