Kotlin类型推断失败
此kotlin代码:Kotlin类型推断失败,kotlin,type-inference,kotlin-null-safety,Kotlin,Type Inference,Kotlin Null Safety,此kotlin代码: 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
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
}
全部已编译。那么,为什么类型推断失败了呢
如果我将temp的类型更改为
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(文本:字符串?):布尔值{
if(text==null){
返回真值
}
var temp=文本
if(false){
temp=String.format(“%s”,文本)
}
返回temp.isBlank()//通过将text
赋值给temp
,temp的类型也将变成String?
。如下所示:
var temp: String? = text
由于您的if(false)
将永远不会执行,因此它对代码没有任何影响。else
添加了一个始终执行的块(因为它基本上意味着if(true)
)并将字符串
分配给不可为空的临时
。由于在第二个示例中临时不可为空,您不必再使用安全调用运算符…通过将文本
分配给临时
,临时类型也将变为字符串?
。如下所示:
var temp: String? = text
由于您的if(false)
将永远不会执行,因此它对代码没有任何影响。else
添加了一个始终执行的块(因为它基本上意味着if(true)
)并将一个字符串
分配给不可为空的temp
。由于在第二个示例中temp不可为空,因此您不必再使用安全调用运算符…之后您可能会认为
if (text == null) {
return true
}
text
的类型被细化为String
,而不是String?
但似乎不是这样;相反,编译器在看到文本
用于需要字符串
的地方时插入智能强制转换
var temp = text
行没有理由插入强制转换,因此编译器不插入,并且temp
的类型是String?
如果你写信
var temp: String = text
if (...) {
temp = Arrays.deepToString(arrayOf(text))
} else {
temp = Arrays.deepToString(arrayOf(text))
}
强制转换是必需的,因此编译器会插入它
如果你写信
var temp: String = text
if (...) {
temp = Arrays.deepToString(arrayOf(text))
} else {
temp = Arrays.deepToString(arrayOf(text))
}
编译器会看到,无论发生什么情况,temp
都被分配了一个值,该值可以再次智能转换为String
。如果没有else
分支,则不会发生这种情况
编辑:
奇怪的是,如果您只是删除if
并离开
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp = text
return temp.isBlank()
}
它确实可以编译,如果我的解释是完整的,我也不会期望它会编译。因此编译器确实维护了智能转换所需的信息,但它似乎没有得到应用,因为
更具体地说,智能强制转换根据以下规则适用:
var
local variables-如果变量未在检查和使用之间修改,则不会在修改它的lambda中捕获,并且不是本地委托属性
在if-else
案例中,两个分支中的赋值一起作为另一个检查;在if
-only案例中,一个分支不起作用。之后您可能会认为
if (text == null) {
return true
}
text
的类型被细化为String
,而不是String?
但似乎不是这样;相反,编译器在看到文本
用于需要字符串
的地方时插入智能强制转换
var temp = text
行没有理由插入强制转换,因此编译器不插入,并且temp
的类型是String?
如果你写信
var temp: String = text
if (...) {
temp = Arrays.deepToString(arrayOf(text))
} else {
temp = Arrays.deepToString(arrayOf(text))
}
强制转换是必需的,因此编译器会插入它
如果你写信
var temp: String = text
if (...) {
temp = Arrays.deepToString(arrayOf(text))
} else {
temp = Arrays.deepToString(arrayOf(text))
}
编译器会看到,无论发生什么情况,temp
都被分配了一个值,该值可以再次智能转换为String
。如果没有else
分支,则不会发生这种情况
编辑:
奇怪的是,如果您只是删除if
并离开
fun badKotlin(text: String?): Boolean {
if (text == null) {
return true
}
var temp = text
return temp.isBlank()
}
它确实可以编译,如果我的解释是完整的,我也不会期望它会编译。因此编译器确实维护了智能转换所需的信息,但它似乎没有得到应用,因为
更具体地说,智能强制转换根据以下规则适用:
var
local variables-如果变量未在检查和使用之间修改,则不会在修改它的lambda中捕获,并且不是本地委托属性
在if-else
的情况下,两个分支中的赋值一起作为另一个检查;在if
-的情况下,只有一个分支没有。Hm,但是如果我将temp的类型更改为var-temp:String=text
,它将被成功地复制!因此,如果我们像这样更改temp
的赋值:temp=String.format(“%s”,text)
它也被编译。有趣的部分是为什么if(text==null){return true}
不会使text
aString
.Hm,但是如果我将temp的类型更改为var-temp:String=text
它成功地复制了!因此,如果我们像这样更改temp
的赋值:temp=String.format(“%s”,text)
它也会被编译。有趣的部分是为什么if(text==null){return true}
不会使text
字符串var temp=text
平均temp
为空,并且if(false)
从未发生过的块不会使其变为非空。在案例2中,数组.deepToString(arrayOf(text))
始终执行,以使temp变为非空。是的,但请注意回答我建议使用isNullOrBlank()
方法。var-temp:String=text
和temp=String.format(“%s”,text)
使temp
不为空。因此,您的代码可以编译。var-temp:String=text
表示temp
为字符串,不为空,并从text
中取值