Null Safety
Prerequisites: Basic types and type inference
null means "no value". In many languages, any variable can
unexpectedly be null, and using it crashes the program with a
NullPointerException — famously called a "billion-dollar mistake".
Kotlin's null safety prevents this at compile time.
Real-world analogy: a nullable value is a parcel that might be an empty box. Kotlin makes you check before you unpack it.
Nullable and non-nullable types
By default, a type can't hold null. Add ? to allow it:
fun main() {
val name: String = "Ada"
val nickname: String? = null
println(name.length)
println(nickname == null)
}
3
true
String and String? are different types. Trying to put null into a
String doesn't compile:
Null cannot be a value of a non-null type 'String'.
You can't use a nullable value directly
fun main() {
val nickname: String? = "Addy"
println(nickname.length)
}
error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'String?'.
That error is Kotlin protecting you: nickname might be null, so you
must handle that case first. The next lesson shows the tools for it.
Where nulls come from
Many functions return a nullable value when something might not exist:
fun main() {
println("42".toIntOrNull())
println("forty".toIntOrNull())
println(listOf<Int>().firstOrNull())
println(mapOf("a" to 1)["b"])
}
42
null
null
null
Functions ending in OrNull return null instead of throwing an error,
and looking up a missing map key gives null.
Common mistakes
- Making everything nullable "just in case". Only add
?when a value can genuinely be missing — every nullable adds checks for the reader.