example:
fun main(){
var userInput: String?
//userInput = null
userInput = "asbdef"
var inputLength:Int? = userInput!!.length
println("Length of the string is :"+inputLength)
}
Output : Length of the string is :6
fun main(){
var userInput: String?
userInput = null
//userInput = "asbdef"
var inputLength:Int? = userInput!!.length
println("Length of the string is :"+inputLength)
}
Output : Unresolved reference: length
I want to know why it gives compile error?
If I just replace (!!) operator with (?) it compiles well but prints output as null.
PS: I'm newbie in Kotlin
The ?.
operator short-circuits if the left side evaluates to null
. So the result of nullVariable?.length
is null
and .length
is never evaluated. Your first example is effectively doing:
println("Length of the string is :" + null)
The !!
operator says "throw a NullPointerException
if the left side is null. Otherwise, we know it's not null on the right side". You can see this if you change your second example a little:
val userInput: String? = null
val inputLength:Int = userInput!!.length // throws NullPointerException
However, I'm not sure why are you are getting Unresolved reference: length
. It looks like that the compiler is doing some optimization when you assign null
directly to userInput
, so rather than compiling it to a String?
which throws an NPE at runtime, it knows the value is only null
(not String?
) at compile time, and therefore can't have the length
property because null
is not a reference.
You can force it to give you to NullPointerException
by adding a layer of abstraction via a function call:
fun main(){
var userInput: String? = "foo"
userInput = alwaysNull()
val inputLength:Int = userInput!!.length // NullPointerException
}
fun alwaysNull(): String? = null
I don't see anything n the Null Safety documentation about the difference in behaviour between initializing in one line / via a function call vs. assigning null
directly to a var though, so what's happening under the hood to get Unresolved reference
is just a guess.