Kasra
Kasra

Reputation: 3155

Kotlin: Null check in if block

I started to learn Kotlin recently. One thing I can't get my head around is the null check blocks. The following statement is considered unsafe, and the compiler won't allow you to compile this.

    var testVar: String? = null;

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

But when you uncomment the if line, everything works. This seems great.

But what if // Doing some work.... is computationally expensive and another thread changes the value of testVar to null while this thread is in // Doing some work line? In this scenario:

Upvotes: 0

Views: 191

Answers (1)

Kevin Coppock
Kevin Coppock

Reputation: 134714

In your initial example, is your var local to a function? For example:

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

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

In this case, no other scope has reference to testVar so nothing else can change it. However, if the var is a class property, i.e.

class MyClass {
    var testVar: String? = null

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

This will fail to compile as testVar could have been set to null by another thread in between the check and the usage.

Going further, if you try to be tricky:

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

    fun trickyFunction() {
        testVar = null
    }

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

The compiler will fail as your variable is captured by a changing closure. So in general, if you are able to use the variable via a smart-cast to non-null, you should not have to worry about any potential for NPEs.

For the second scenario (var properties) it is preferable to rely on .let to capture an immutable reference to the current value, i.e.

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

Upvotes: 3

Related Questions