Reputation: 650
I'm new to Kotlin and I don't know why compiler complains about this code:
data class Test(var data : String = "data")
fun test(){
var test: Test? = Test("")
var size = test?.data.length
}
Compiler complains with test?.data.length
, it says that I should do: test?.data?.length
. But data variable is String
, not String?
, so I don't understand why I have to put the ?
when I want to check the length.
Upvotes: 11
Views: 5982
Reputation: 147901
The expression test?.data.length
is equivalent to (test?.data).length
, and the test?.data
part is nullable: it is either test.data
or null
. Therefore it is not null-safe to get its length
, but instead you should use the safe call operator again: test?.data?.length
.
The nullability is propagated through the whole calls chain: you have to write these chains as a?.b?.c?.d?.e
(which is, again, equivalent to (((a?.b)?.c)?.d)?.e
), because, if one of the left parts is null, the rest of the calls cannot be performed as if the value is not-null.
Upvotes: 11
Reputation: 23105
If you don't want to use safe call before each non-nullable component of the call chain, you can get the result of the first safe call into a new variable with the standard extension functions run
or let
:
// `this` is non-nullable `Test` inside lambda
val size = test?.run { data.length }
// or: `it` is non-nullable `Test` inside lambda
val size = test?.let { it.data.length }
Note that size
is still nullable Int?
here.
Upvotes: 3