Nullable Types
How Kotlin's type system distinguishes values that can be null from values that never can, catching a huge class of bugs at compile time.
2 min de lectura
Null pointer exceptions have caused so many production crashes across so many languages that their inventor, Tony Hoare, has called null references his "billion-dollar mistake." Kotlin's answer isn't to remove null — sometimes "no value" is a legitimate state — but to make the possibility of null part of the type itself, so the compiler can force you to deal with it.
Every type is non-null by default
In Kotlin, a regular type like String can never hold null:
val name: String = "Alice"
val name: String = null // Compile error: null can not be a value of a non-null type StringThis is the default, and it's a strong guarantee: if a function takes a String parameter, you know — with the compiler's backing — that it will never receive null. No defensive if (name != null) check needed.
Opting into null with ?
When a value genuinely might be absent, mark the type with a trailing ?:
val name: String? = null // fine — String? allows null
var nickname: String? = "Al"
nickname = null // also fineString and String? are different types as far as the compiler is concerned. You can assign a String to a String? variable freely (a real value is always a valid "maybe a value"), but not the other way around without a check.
The compiler won't let you forget
The real payoff shows up the moment you try to use a nullable value the same way you'd use a non-null one:
val nickname: String? = getNickname()
println(nickname.length) // Compile error: only safe (?.) or non-null asserted (!!.) calls are allowedThat's not a runtime crash waiting to happen in production — it's a compile-time error, caught before the code ever ships. The compiler is refusing to let you call .length on something that might not exist.
Narrowing with a null check
If you check for null first, Kotlin's compiler is smart enough to treat the variable as non-null for the rest of that scope — a feature called smart casting:
val nickname: String? = getNickname()
if (nickname != null) {
// Kotlin knows nickname can't be null here
println(nickname.length)
}Smart casting only works on vals (or vars the compiler can prove aren't modified elsewhere), because a mutable variable could theoretically be set back to null by another thread between the check and the use.
Why this matters
This is arguably Kotlin's most distinctive feature, and the reason so many teams adopt it specifically to reduce crashes: a NullPointerException becomes something the compiler catches while you're writing the code, rather than something a user discovers in production. The next lesson covers the two operators — ?. and ?: — that make working with nullable values concise instead of tedious.