Kotlin 类型推断失败
Kotlin type inferrence failed
这个科特林代码:
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 的分配:temp = String.format("%s", text)
它也会被编译。
更新:
编译成功:
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp = text
if (false) {
temp = String.format("%s", text)
}
return temp.isBlank() // <-- only safe (?.) or non null asserted (!!.) calls
}
还有这个:
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp: String = text
if (false) {
temp = Arrays.deepToString(arrayOf(text))
}
return temp.isBlank() // <-- only safe (?.) or non null asserted (!!.) calls
}
通过将 text
分配给 temp
,temp 的类型也将变为 String?
。像这样:
var temp: String? = text
因为你的 if (false)
永远不会被执行,所以它对代码没有任何影响。 else
添加了一个总是被执行的块(因为它基本上意味着 if (true)
)并分配一个 String
给 temp
是不可空的。由于在第二个示例中 temp 不可为空,因此您不必再使用 safe-call 运算符...
你可能会想
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!
,它又可以是 smart-cast 到 String
。没有 else
分支,这不会发生。
编辑:
奇怪的是,如果您只是删除 if
并留下
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp = text
return temp.isBlank()
}
它确实可以编译,如果我的解释是完整的,我不希望它编译。所以编译器确实维护了智能转换所需的信息,但它似乎没有被应用,因为
More specifically, smart casts are applicable according to the following rules: ...
var
local variables - if the variable is not modified between the check and the usage, is not captured in a lambda that modifies it, and is not a local delegated property;
在if-else
情况下,两个分支中的赋值一起作为另一个检查;在 if
-only,一个分支没有。
这个科特林代码:
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 的分配:temp = String.format("%s", text)
它也会被编译。
更新:
编译成功:
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp = text
if (false) {
temp = String.format("%s", text)
}
return temp.isBlank() // <-- only safe (?.) or non null asserted (!!.) calls
}
还有这个:
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp: String = text
if (false) {
temp = Arrays.deepToString(arrayOf(text))
}
return temp.isBlank() // <-- only safe (?.) or non null asserted (!!.) calls
}
通过将 text
分配给 temp
,temp 的类型也将变为 String?
。像这样:
var temp: String? = text
因为你的 if (false)
永远不会被执行,所以它对代码没有任何影响。 else
添加了一个总是被执行的块(因为它基本上意味着 if (true)
)并分配一个 String
给 temp
是不可空的。由于在第二个示例中 temp 不可为空,因此您不必再使用 safe-call 运算符...
你可能会想
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!
,它又可以是 smart-cast 到 String
。没有 else
分支,这不会发生。
编辑:
奇怪的是,如果您只是删除 if
并留下
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp = text
return temp.isBlank()
}
它确实可以编译,如果我的解释是完整的,我不希望它编译。所以编译器确实维护了智能转换所需的信息,但它似乎没有被应用,因为
More specifically, smart casts are applicable according to the following rules: ...
var
local variables - if the variable is not modified between the check and the usage, is not captured in a lambda that modifies it, and is not a local delegated property;
在if-else
情况下,两个分支中的赋值一起作为另一个检查;在 if
-only,一个分支没有。