我按照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.length
是b != 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将正确地推断
b
是String
类型,因为您已将其明确设置为String(“Kotlin”)。在这里我们应该注意,String
类型永远不能包含null。知道这一点,就不需要b != null
语句的if
部分。但是,在对它进行评估(始终为true)之后,它将评估b.length
,因为b
是String
,因此具有length
属性。这个例子应该可以编译(我没有测试)。接下来...
val b = null
if (b != null && b.length > 0) {
...
}
这段代码不会编译,让我们回顾一下原因...
这段代码看起来确实很相似,但有很大的不同。在这种情况下,因为您只是将
b
设置为null
,所以Kotlin会推断b
是Nothing?
。它没有有关您想要b
的类型的信息,并且已将其设置为null(并且由于它是val
,因此始终为null
)。因为b
是null
,所以它使b
可为空。因此,鉴于此,当我们编译
b != null
时,它将总是失败,因为b
永远不可能是不是null
的东西。可是等等!我们正在编译...当我们遇到b.length
时,由于Nothing?
没有length
属性,因此Kotlin将引发编译错误!本质上,通过将
b
设置为null
而不提供类型提示,Kotlin将采用唯一的路径来推断类型-Nothing?
。关于Kotlin的逻辑 'and'不会短路吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54498548/