Skip to content
AgileLogics
7 min read

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