Working with Nullable Values
Prerequisites: Null safety
Kotlin gives you several tools for nullable values. Knowing which to use is a daily Kotlin skill.
Safe call: ?.
?. calls a property or function only if the value isn't null;
otherwise the whole expression is null:
fun main() {
val nickname: String? = null
val city: String? = "Oslo"
println(nickname?.length)
println(city?.length)
println(city?.uppercase()?.reversed())
}
null
4
OLSO
Elvis operator: ?:
?: provides a fallback when the left side is null:
fun main() {
val saved: String? = null
val name = saved ?: "Guest"
println(name)
val quantity = "abc".toIntOrNull() ?: 1
println(quantity)
}
Guest
1
The result of saved ?: "Guest" is a plain, non-null String.
Smart casts
After you check that a value isn't null, Kotlin treats it as
non-null automatically:
fun describe(input: String?) {
if (input == null) {
println("Nothing entered")
return
}
println("You typed ${input.length} characters") // input is String here
}
fun main() {
describe("hello")
describe(null)
}
You typed 5 characters
Nothing entered
This is called a smart cast. The early return for the missing case
— a guard clause — keeps the main code simple.
Elvis and return combine neatly: val name = input ?: return.
let: run code only if not null
fun main() {
val email: String? = "ada@example.com"
email?.let { println("Sending to $it") }
val missing: String? = null
missing?.let { println("Never printed") }
}
Sending to ada@example.com
Inside the braces, it is the non-null value. (Braces like these are
lambdas, covered in their own lesson.)
Not-null assertion: !! (avoid)
!! says "I'm sure this isn't null". If it is, the program crashes:
fun main() {
val value: String? = null
println(value!!.length)
}
Exception in thread "main" java.lang.NullPointerException
Treat !! as a warning sign. There's almost always a safer option.
Which to use
| Situation | Use |
|---|---|
Get a property if present, else null |
?. |
| A sensible default exists | ?: |
| Can't continue without the value | if (x == null) return or ?: return |
| Do something only if present | ?.let { } |
null would be a bug in your own code |
!! (rarely) |
Practice
Write fun parseAge(text: String): Int that returns the number in
text, or 0 if it isn't a valid number. Call it with "36" and
"abc".
Show solution
fun parseAge(text: String): Int = text.toIntOrNull() ?: 0
fun main() {
println(parseAge("36"))
println(parseAge("abc"))
}
36
0