user7863932
user7863932

Reputation: 21

Return value for a variable that apparently can be null but really can't

What's an idiomatic way to do code this in Kotlin?

   private var someVar: SomeClass? = null

   private fun getSomeVar(): SomeClass {
        if (someVar == null) {
            someVar = getDefaultSomeVar()
        }

        return someVar
    }

Android Studio warns me about the return type. In Java this code is, however, proper and idiomatic. I mean, instead of changing the return type to SomeClass? maybe there's still a better way?

Actually, getSomeVar() can never return null

Upvotes: 2

Views: 207

Answers (3)

A. Shevchuk
A. Shevchuk

Reputation: 2169

It could be shorter and without any warnings

 private fun getSomeVar(): SomeClass {
        return someVar?:getDefaultSomeVar()
    }

Upvotes: 0

RobCo
RobCo

Reputation: 6495

The compiler complains because, theoretically, a different thread could change someVar in between the assignment and the return statement.

The idiomatic solution here would be to use property delegation:

private val someVar: SomeClass by lazy { getDefaultSomeVar() }

This initializes the property when it is first accessed in a thread safe manner. Also note that it is now a non-nullable val, instead of a nullable var, which makes it generally easier to work with.

You do lose the ability to modify it later on. If it needs to be mutable you currently have to make that yourself. For an example implementation see this SO question: Kotlin lazy default property


The following two solutions take the method in the question (the 'java way') for granted and just show a way to prevent the compiler warning. However, in your situation these are not advised as they both have drawbacks over the lazy initialized property:

1) Introduce a local variable. This variable is safe from being mutated by other threads and allows the compiler to do a Smart Cast:

private fun getSomeVar(): SomeClass {
    var value = someVar
    if(value == null) {
        value = getDefaultSomeVar()
        someVar = value
    }

    return value
}

The method itself is however still not thread safe. In a multithreaded environment, getDefaultSomeVar() could be called multiple times and it is not guaranteed that the returned value of this method is equal to someVar.

2) Use !!: the double bang operator. This converts a nullable type to non-nullable. But now you lose the protection and null safety that the kotlin compiler enforces on you.

return someVar!!

As the documentation puts it: 'If you want an NPE, you can have it'

Upvotes: 5

John
John

Reputation: 1314

You can write:

return someVar!!

this will return a non-null value, however if it's null it will throw an NPE.

Upvotes: 0

Related Questions