ItIsJustMe
ItIsJustMe

Reputation: 113

?. operator on a nullable array

I have a method which returns an array, on with I check that a certain index is set. In Java, I would do:

if (obj.method() != null && obj.method()[some_index] != null) {
   ...
}

Is it possible to shorten this in Kotlin with the ?. operator?

The following non-functional pseudo-code gives an idea what I am after:

if (obj.method()?.[some_index]) {
   ...
}

Upvotes: 4

Views: 91

Answers (2)

Slaw
Slaw

Reputation: 46180

At least in Kotlin 2.0.0 (haven't tried it in older versions), you can define a get operator extension function for a nullable array receiver and implement it to return null if the array itself is null.

operator fun <T> Array<T>?.get(index: Int): T? = this?.get(index)

Then you can use ?.let { } on the result of the access just like @broot's answer demonstrates, but now you can change this:

obj.method()?.get(some_index)?.let {
    // ...
}

To this:

obj.method()[some_index]?.let {
    // ...
}

Whether or not that is preferable is up to you. One advantage is the syntax looks cleaner, at least in my opinion. But one disadvantage is that it's no longer clear that the array returned by method() is itself nullable.


Executable example:

operator fun <T> Array<T>?.get(index: Int): T? = this?.get(index)

fun main () {
    printArray(arrayOf(Person("John"), Person("Bob"), null, Person("Amy"), null))
    printArray(null)
}

fun printArray(array: Array<Person?>?) {
    println("array = ${array?.contentToString()}")
    // hard-coded loop for example
    for (i in 0..4) {
        // here's the [i]?.let { } syntax enabled by the 'get'
        // extension operator function above
        array[i]?.let { println("  $it") }
    }
    println()
}

data class Person(val name: String)

Output:

array = [Person(name=John), Person(name=Bob), null, Person(name=Amy), null]
  Person(name=John)
  Person(name=Bob)
  Person(name=Amy)

array = null

Note when the array is null nothing is printed because the let doesn't execute. And when the array is non-null, the let only executes when the element in the array is also non-null.

Upvotes: 2

broot
broot

Reputation: 28432

Yes, we can shorten this by replacing the operator with its equivalent function call:

if (obj.method()?.get(some_index) != null)

If we need to access the value from the array if it exists and isn't null, we can additionally use let:

obj.method()?.get(some_index)?.let {
    println(it) // `it` is the value
}

Upvotes: 7

Related Questions