Safe call operator chain


#1
class A(val b: Int)

fun main(args: Array<String>) {
    val b : Int? = null
    val a = if (b != null) { A(b) } else { null }
    println(a?.b.toString().length)
}

I thought a?.b.toString().length will return null, but instead it does null.toString().length
What are the reasons to work so? Why not return null on first null property?


#2

https://kotlinlang.org/docs/reference/null-safety.html#safe-calls


#3

I know about documentation, and there are nothing about reasons why it works so.


#4

toString() is an extension function that can handle null: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/to-string.html


#5

The documentation says:

b?.length

This returns b.length if b is not null, and null otherwise. The type of this expression is Int?

So if we apply this to your code, and to make it easier to understand we unchain the calls, we have the following code:

val op1: Int? = a?.b
val op2: String = op1.toString()
val op3: Int = op2.length

println(op3)

The safe call does not stop execution as soon as it finds a null value, it simply skips that call and returns null, so if you want to print null if a == null you should write it like this: println(a?.b?.toString()?.length)

Usually, if you make a safe call, all the chained calls following the first one need to be safe calls as well, but as @jstuyts pointed out: