Kotlin中的非空检查有什么区别?

时间:2018-12-26 08:30:28

标签: kotlin kotlin-null-safety

有几种方法可以在Kotlin中执行空检查:

1。

if(myVar != null) {
    foo(myVar)
}

2。

myVar?.let { 
    foo(it)
}

3。

myVar?.run { 
    foo(this)
}

这两种方式有什么区别?

有什么理由(性能,最佳实践,代码风格等)为什么我应该比其他人更喜欢?

7 个答案:

答案 0 :(得分:0)

在操作方式上,所有三个代码的行为均相同。

?。用于连锁经营。

 bob?.department?.head?.name // if any of the properties in it is null it returns null

要仅对非空值执行链式操作,可以将安全调用运算符与let一起使用

myVar?.let { 
foo(it)
}

上面的代码对于代码的样式和性能非常有用

更多详细信息,请参见Null Safety

答案 1 :(得分:0)

对于Kotlin,方法2和3更惯用。这两个功能非常相似。参数传递没有什么区别。

例如,我们有一个可为空的变量:

var canBeNull: String? = null

使用T.run时,将使用扩展函数调用,并在闭包中传递this

    canBeNull?.run {
        println(length) // `this` could be omitted
    }

调用T.let时,可以像lambda参数it一样使用它。

    canBeNull?.let {
        myString -> println(myString.length) // You could convert `it` to some other name
    }

关于Kotlin标准函数的不错的article

答案 2 :(得分:0)

这三个大致相等。

if情况与大多数其他语言更相似,因此许多开发人员可能会觉得它更易于阅读。

但是,一个区别是if的情况将读取myVar的值两次:一次用于检查,然后一次将其传递给foo()。这会有所不同,因为如果myVar是一个属性(即可能被另一个线程更改的东西),则编译器将警告说,在之后校验。如果这是一个问题(例如,因为foo()期望使用非null参数),则需要使用其他情况之一。

因此,let案例在Kotlin中已成为相当普遍的做法。 (run情况几乎是同一件事,但是由于某种原因,这种情况并不受欢迎。我不知道为什么。)

解决该问题的另一种方法是将myVar分配给一个临时值,对其进行测试然后再使用。这也更像其他语言,但是更冗长。许多人更喜欢let情况的简洁性,尤其是当myVar实际上是一个复杂的表达方式时。

答案 3 :(得分:0)

您问题中的示例并未显示出做出决定的真正原因。

首先,由于您未使用foo的返回值,因此,您既不应使用let也不要使用run。您可以在alsoapply之间进行选择。

第二,由于您已经具有要对变量进行空值检查的结果,因此差异会逐渐消失。这是一个更好的激励例子:

complexCall(calculateArg1(), calculateArg2())?.also {
    results.add(it)
}

相对于

val result = complexCall(calculateArg1(), calculateArg2())
if (result != null) {
    results.add(result)
}

第二个示例声明一个标识符result,该标识符现在可用于其余词法范围,即使仅用一行完成它。

另一方面,第一个示例使所有内容保持独立,当您继续阅读其余代码时,您100%确信不必记住{{1 }}。

答案 4 :(得分:0)

!是要告诉编译器,我确定变量的值不为null,如果为null,则抛出null指针异常(NPE),其中as为?。告诉编译器我不确定该变量的值是否为null,如果不确定,则不要抛出任何null指针。

使用可空属性的另一种方法是安全调用运算符?。 如果该属性不为null,则调用该方法;如果该属性为null则返回null而不抛出NPE(空指针异常)。

nullableVariable?.someMethodCall()

答案 5 :(得分:0)

Kotlin具有NullPoint-Exception与Java相比的新功能。

基本上,当我们用Java进行编码时,我们必须检查!!在每一次Flied中。

但是在Kotlin中,这是首先实现的简单方法

假设在科特林

var response:Json?= Null

response:Json?.let {

如果响应不是Null,则此部分将自动处理。...然后,此Block开始执行} ?. run { 这是可空的,但是,我们可以在其中放置交战}因此,建议您使用Kotlin提供的功能开始在Kotlin中工作。

(Flied)?. let {不是空值落在} ?. run {空值代码}

这将处理NullPoint异常或保护您的应用程序免于崩溃

答案 6 :(得分:0)

您要实现的目标

您要实现的是Kotlin编译器对要使用的变量执行smart cast

在您的所有三个示例中,编译器都可以做到这一点。

示例:

if(myVar != null) {
    foo(myVar) // smart cast: the compiler knows, that myVar can never be null here
}

选择

使用哪个选项实际上是样式问题。您不应该经常混合使用。使用它并坚持下去。

您无需担心性能,因为letrun是内联的(请参见inline function)。这意味着它们的代码(主体)在编译时被复制到调用站点,因此没有运行时开销。