Kotlin:如果没有阻止,则空检查

时间:2019-04-15 21:53:04

标签: kotlin

我最近开始学习Kotlin。我无法理解的一件事是空检查块。以下语句被认为是不安全的,并且编译器不允许您对其进行编译。

    var testVar: String? = null;

    // if (testVar != null )
    {
        // Doing some work....
        println(testVar.length)
    }

但是当您取消注释if行时,一切正常。这看起来很棒。

但是如果 // Doing some work....在计算上很昂贵,而另一个线程在testVar行中,则另一个线程将null的值更改为// Doing some work怎么办? ?在这种情况下:

  • 程序是否抛出NullPointerException?
  • 或:
  • 字节码是否缓存testVar的值并使用if块内的缓存值?

1 个答案:

答案 0 :(得分:3)

在您的最初示例中,您的var是函数的局部变量吗?例如:

fun doStuff() {
    var testVar: String? = null

    if (testVar != null) {
        println(testVar.length)
    }
}

在这种情况下,没有其他作用域引用过testVar,因此没有其他更改。但是,如果var是类属性,即

class MyClass {
    var testVar: String? = null

    fun doStuff() {
        if (testVar != null) {
            println(testVar.length)
        }
    }
}

这将无法编译,因为testVar在检查和使用之间可能已被另一个线程设置为null。

走得更远,如果您尝试棘手的话:

fun doStuff() {
    var testVar: String? = null

    fun trickyFunction() {
        testVar = null
    }

    if (testVar != null) {
        trickyFunction()
        println(testVar.length)
    }
}

编译器将失败,因为您的变量被更改的闭包捕获。因此,通常,如果您能够通过智能广播将变量使用为非空值,则不必担心NPE的任何潜在可能性。

对于第二种情况(可变属性),最好依靠.let来捕获对当前值的不变引用,即

testVar?.let { capturedTestVar ->
    println(capturedTestVar.length)
}