0

刚刚学习了替换操作的KotlinNullable类型和功能。let{}if (xx != null) {}

但是我感到困惑的一件事是,我们都知道并且我认为编译器应该知道,当我们使用时let{},调用此函数的变量/对象可能为空,但是编译器仍然要求我添加安全调用运算符“ ?” 在变量名之后,而不是if (xx != null) {}. 为什么?

我的一段代码:

fun main() {
    var number1: Int? = null

    //val number2 = number1.let { it + 1 } ?: 10    //doesn't work, not quite "smart"
    val number2 = number1?.let { it + 1 } ?: 10     //works, must have "?"

    println(number1)
    println(number2)
}
4

1 回答 1

4

您已经在评论中得到了答案,但只是为了解释一下?......

Kotlin 允许您通过在调用之前添加对可空变量和属性进行空安全调用?。你也可以通过这样做来链接它

nullableObject?.someProperty?.someFunction()

它计算nullableObject如果它是非空的,它计算下一位,否则整个表达式计算为null。如果链的任何部分计算为 null,则整个表达式返回 null。

因此它具有这种短路效应,如果您无法将整个链评估为非空结果,则可以使用 elvis "if null" 运算符创建默认值:

nullableObject?.nullableProperty?.someFunction() ?: defaultAction()

一旦你在链中引入了空检查,你必须为之后的每个调用添加它 - 它基本上是传播前一位的结果,或者null它解析为,所以每一步都有一个空检查


let块只是一个范围函数 - 您可以在一个值上使用它,因此您可以使用该值作为参数或接收器(变量或this基本上)运行一些代码。它还具有创建一个新的临时局部变量来保存该值的副作用,因此如果原始值是 a var,则该值是否更改并不重要,因为您的let代码不再引用该变量。

因此,它对于一次进行空值检查很有用,而不必担心在您使用它时底层值可能会变为空值:

nullableVar?.let { it.definitelyIsNotNull() }

并且编译器将识别并智能地将其转换为非空类型。if (nullableVar != null)检查不能保证在nullableVar执行下一行时它不会为空。

于 2020-11-15T22:34:51.650 回答