Kotlin式推理失败了

时间:2018-03-13 04:10:45

标签: kotlin type-inference kotlin-null-safety

这个kotlin代码:

socket.io-client-swift

无法使用消息编译:{{1​​}}

但如果我添加fun badKotlin(text: String?): Boolean { if (text == null) { return true } var temp = text if (false) { temp = Arrays.deepToString(arrayOf(text)) } return temp.isBlank() // <-- only safe (?.) or non null asserted (!!.) calls }

only safe (?.) or non null asserted (!!.) calls are allowed on a nullable receiver of type String?

全部编译。那么,为什么类型推理失败了?

如果我将温度类型更改为else,则会成功复制!所以,此外,如果我们像这样更改临时赋值:fun badKotlin(text: String?): Boolean { if (text == null) { return true } var temp = text if (false) { temp = Arrays.deepToString(arrayOf(text)) } else { temp = Arrays.deepToString(arrayOf(text)) } return temp.isBlank() } 它也被编译。

更新:

成功应对:

var temp: String = text

而且:

temp = String.format("%s", text)

2 个答案:

答案 0 :(得分:2)

你可能会想到

之后
if (text == null) {
    return true
}

text的类型被细化为String而不是String?

但似乎不是;相反,当编译器在需要text的情况下使用String时,编译器会插入智能强制转换。在

var temp = text

行没有理由插入强制转换,因此编译器没有,temp的类型为String?

如果你写

var temp: String = text

必须使用 ,因此编译器会插入它。

如果你写

if (...) {
    temp = Arrays.deepToString(arrayOf(text))
} else {
    temp = Arrays.deepToString(arrayOf(text))
}

编译器发现无论发生什么,temp都被分配了platform type String!的值,再次可以智能转换为String。没有else分支,就不会发生这种情况。

编辑:

奇怪的是,如果你只是删除if并离开

fun badKotlin(text: String?): Boolean {
    if (text == null) {
        return true
    }

    var temp = text

    return temp.isBlank()
}

它确实编译,如果我的解释完成,我不会指望它。因此编译器会保留智能投射所需的信息,但似乎没有应用,因为

  

更具体地说,智能演员表适用于以下规则:...

     
      
  • var局部变量 - 如果在检查和使用之间未修改变量,则不会在修改它的lambda中捕获,并且不是本地委托属性; < / LI>   

if-else案例中,两个分支中的分配一起作为另一个检查;仅在if - 中,一个分支没有。

答案 1 :(得分:1)

通过将text分配给temp,临时类型也会变为String?。像这样:

var temp: String? = text

由于您的if (false)永远不会被执行,因此对代码没有任何影响。 else添加一个始终执行的块(因为它基本上意味着if (true))并将String分配给不可为空的temp。由于在第二个示例中temp不可为空,因此您不必再使用安全调用操作符...