为什么IntelliJ中的"Smart cast to kotlin.String"

Dim*_*ims 1 null intellij-idea kotlin

我用可空的参数写了我的课

class MyClass(a: String? = null) {
    var b: String

    init {
        if( a == null ) {
            b = "N/A"
        }
        else {
            b = a
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并注意到,IntelliJ警告b = a任务

Smart cast to kotlin.String
Run Code Online (Sandbox Code Playgroud)

为什么这个警告以及如何避免它?

s1m*_*nw1 6

这不是一个警告,只是编译器知道您的变量的信息a null.因此,它可以用作String代替可空的String?,因此没有安全操作符,例如

否则,您需要显式a: String?转换String为使其可分配给String变量b,如以下屏幕截图所示:

在此输入图像描述


zsm*_*b13 5

这不是要避免的事情,这是一种称为智能转换的语言功能。

编译器已检测到它a是给定代码路径上的非空值,因此您可以使用不可为空的String类型来使用它,这样您就可以直接使用它,而不必担心其可为空性。如果您没有获得智能转换,则必须手动将其从 a转换String?为 aString才能调用其上的方法 - 或者将其分配给不可为 null 的变量,就像您的情况一样。


另一个可能更容易理解智能转换何时启动的示例是子类。假设您有PersonCustomer类,只有后者有一个getPurchases()方法。

在 Java 中,您必须执行以下操作才能调用所述方法:

if (p instanceof Customer) {
    ((Customer)p).getPurchases();
}
Run Code Online (Sandbox Code Playgroud)

在 Kotlin 中,您可以在块内智能转换if为您已经检查过的子类型:

if (p is Customer) {
    p.getPurchases()
}
Run Code Online (Sandbox Code Playgroud)

如果您考虑一下,从String?到 的转换String在工作中是相同的机制 - 您也得到了到更具体类型的智能转换。

if (a != null)
Run Code Online (Sandbox Code Playgroud)

给定a的类型String?基本相同

if (a is String)
Run Code Online (Sandbox Code Playgroud)