Null Safety
🛡️ Null Safety
❓ Nullable Types
In Kotlin, a type is non-nullable by default. To allow null, the type must be explicitly marked with a trailing ?:
This is the core idea of the whole chapter: String and String? are genuinely different types to the compiler. Every function, property, and variable declares up front whether null is a possibility — and the compiler then forces you to handle that possibility before you can use the value.
Null Handling: Java vs JavaScript vs Kotlin
| Language | Can any reference be null? | Compiler enforcement |
|---|---|---|
| Java | Yes, any object reference | None — NPE is a runtime crash |
| JavaScript | Yes, plus a separate undefined | None — TypeError at runtime |
| Kotlin | Only types explicitly marked with ? | Compile error if unchecked |
🔗 The Safe Call Operator: ?.
Calling a method or property directly on a nullable type is a compile error — Kotlin won't let you risk it. The safe call operator ?. calls through only if the value isn't null, and evaluates to null otherwise:
Safe calls chain naturally: user?.address?.city walks the chain and evaluates to null the moment any link in it is null, instead of crashing partway through — the same idea as JavaScript's optional chaining (user?.address?.city), which was directly inspired by this Kotlin feature.
🎸 The Elvis Operator: ?:
The Elvis operator provides a fallback value when the left-hand side is null — named for the way ?: looks like Elvis Presley's hairstyle turned sideways:
?. — "call it if it's there"
Short-circuits to null instead of crashing when the receiver is null. Read a?.b as "get b from a, but only if a exists."
?: — "or fall back to this"
Supplies a default when the left side is null. Read a ?: b as "use a, or b if a is null." The two operators combine constantly: a?.b ?: c.
🎯 Smart Casts
After an explicit null check, the compiler "remembers" that a value can't be null within that scope, and lets you use it as the non-nullable type automatically — no manual cast required:
This is one of Kotlin's quieter but most useful conveniences: Java requires an explicit cast even after a null check (or a local variable copy to avoid a "value could change" warning), while Kotlin's compiler tracks the null-checked state of a val automatically.
The !! operator forces a nullable value to be treated as non-null, and throws a NullPointerException immediately if it turns out to be null after all: nickname!!.length. It exists for cases where you're certain a value can't be null but the compiler can't prove it — but reaching for it regularly defeats the entire point of Kotlin's null safety system. Prefer ?. and ?:; treat !! as a last resort, not a habit.
💻 Coding Challenges
Challenge 1: Safe Call Chains
Declare a nullable val city: String? = null. Use println with the safe call operator to print its length — it should print null without crashing. Then set city to "London" in a second variable and print its length again, this time getting an actual number.
Goal: See ?. short-circuit safely on both a null and a non-null value.
Challenge 2: Elvis Operator Defaults
Write a function displayName(nickname: String?): String that returns the nickname if present, or "Anonymous" otherwise, using the Elvis operator in a single-expression function. Call it with both a null and a non-null argument and print both results.
Goal: Practice ?: as a compact default-value pattern.
Challenge 3: Smart Casts
Write a function describeAge(age: Int?) that checks with an if whether age is not null. Inside the non-null branch, use the smart-cast value directly (no ?. or !!) to print whether it's even or odd. In the else branch, print "Age unknown".
Goal: See the compiler treat a null-checked nullable value as non-nullable automatically.
Null safety is consistently cited as the single biggest reason teams migrated from Java to Kotlin for Android work — NullPointerExceptions were historically one of the most common crash causes in Android apps. Moving null-checking from "something you remember to do" to "something the compiler enforces" eliminates an entire category of bugs at the source.
🎯 What's Next
Next chapter: Classes & Data Classes — constructors, properties, data classes, copy(), and companion objects.