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

此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 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
a
String
.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
中取值