Anyone know why this doesn’t work ```val nullableF...
# getting-started
a
Anyone know why this doesn’t work
Copy code
val nullableFoo: Any? = null
val nonNullFoo = nullableFoo != null
if (nonNullFoo) {
   acceptsNonNullFoo(nullableFoo) // expected Any but is Any?
}
but this works
Copy code
val nullableFoo: Any? = null
if (nullableFoo != null) {
   acceptsNonNullFoo(nullableFoo)
}
🤔
j
The compiler doesn't analyze the program to this extent (as far as flow analysis is concerned), so it doesn't link the null check on
nonNullFoo
boolean variable to the fact that
nullableFoo
is not null when considering the
if
statement. In the second snippet, it is able to detect that because it's a direct null check on that variable, so smart casting can work.
a
I see. In actual
nonNullFoo
boolean has more conditions, but
nullableFoo != null
seems should be true 100% of the time. Any tips how to handle this in code? It feels weird to have to do
Copy code
if (nonNullFoo && nullableFoo != null)
again
v
acceptsNonNullFoo(nullableFoo!!)
a
^ that bit me in the a$$ too quickly. I removed
nonNullFoo
and got a crash because I forgot about the
!!
😄
a
have you looked at contracts? https://www.baeldung.com/kotlin/contracts You can write a custom 'validate not null' method, which the compiler will understand
Copy code
@ExperimentalContracts
private fun validate(request: Request?) {
    contract {
        returns() implies (request != null)
    }
    if (request == null) {
        throw IllegalArgumentException("Undefined request")
    }
    if (request.arg.isBlank()) {
        throw IllegalArgumentException("No argument is provided")
    }
}
d
Such smartcasts will work in K2 compiler
🆒 8