代码之家  ›  专栏  ›  技术社区  ›  Kurt Peek

科特林的逻辑和不短路?

  •  1
  • Kurt Peek  · 技术社区  · 6 年前

    我在跟踪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想法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 . 这让我吃惊,因为我认为第一个检查是“短路”布尔表达式(如果需要),然后调用 B.长度 “安全”。

    例如,在python中,可以这样做:

    In [1]: "foo" == "bar" and what.the.heck
    Out[1]: False
    

    即使这样也行 what 未定义,因为 and “停止” "foo" 不等于 "bar" .

    科特林就是这样工作的吗?似乎缺少python的“短路”功能是一个限制。

    2 回复  |  直到 6 年前
        1
  •  8
  •   Todd    6 年前

    Kotlin && 操作员将短路(就像Java),但只在运行时。你所经历的是 编译时间 错误。特别是当将Kotlin(或Java)与Python进行比较时,最大的不同在于Kotlin和Java是静态类型的,并且有编译阶段。因此,如果类型不匹配,则会出现编译错误。

    让我们一次一个地检查一下……

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

    在这种情况下,Kotlin会正确推断 b 是类型 String ,因为您清楚地将其设置为字符串(“kotlin”)。我们应该注意到 类型不能包含空值。知道了这一点, b != null 你的一部分 if 陈述是不必要的。但是,在评估之后(始终为真),它将评估 b.length 因为 是一个 因此有一个 length 财产。这个例子 应该 编译良好(我没有测试它)。

    然后…

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

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

    这个代码看起来 真的? 类似但有一个巨大的区别。在这种情况下,因为你刚刚设置 null 科特琳会推断出 是一个 Nothing? . 它没有关于您想要什么类型的信息 是的,并且您已将其设置为空(因为它是 val 它会 总是 无效的 )因为 无效的 它使 可空的。

    因此,考虑到这一点,当我们编译 B!=空 ,那将 总是 失败,因为 不可能是不可能的 无效的 . 但是等等!我们正在编译…当我们遇到 B.长度 科特琳会扔一个 编译错误 因为 没有什么? 没有一个 长度 财产!

    基本上,通过设置 无效的 并且不提供类型提示,Kotlin采用它可以推断类型的唯一路径- 没有什么? .

        2
  •  1
  •   Strom    6 年前

    从您的链接文本:“请注意,这仅适用于b不可变的情况(即在检查和使用之间未修改的局部变量或具有支持字段且不可重写的成员val)”。

    val b=null 是不可变的,但由于不能推断或存储空值类型,因此不能在有效快捷方式中将其用作源。

    如果您改为代码来给它一个可以为空的类型,并设置为空,那么这就可以工作了。