The null problem Kotlin was designed to fix
This is the module that most explains why Kotlin exists. If you take one thing from the whole course into your Android career, let it be how Kotlin handles the absence of a value — because the mistake it prevents is, by a wide margin, the most common cause of application crashes in the languages that do not.
The mistake, and its price
In 2009, Tony Hoare — who invented the null reference in 1965 — called it his "billion-dollar mistake":
"I call it my billion-dollar mistake… I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement."
The problem: in most languages, any reference can be null (absent), and the compiler does not
force you to check. So you write code assuming a value is there, it is not, and the program crashes
at runtime with a null pointer exception — the infamous NullPointerException (NPE) in Java,
the "undefined is not a function" in JavaScript, the segfault in C. It is the single most frequent
crash in production software, and it happens because the type system did not know a value could be
missing.
Concretely, in Java:
String name = getName(); // might return null
int length = name.length(); // NullPointerException if it did — and it compiled fine
That code compiles without complaint and crashes in front of a user. The compiler had no idea
name could be null, so it could not warn you. Multiply that across a large app and a team, and you
have the billion dollars.
Kotlin's fix: absence is part of the type
Kotlin's insight is simple and profound: make "can be null" part of the type, and let the compiler enforce the check. By default, a Kotlin type cannot hold null:
val name: String = "Kavita"
val name2: String = null // error: null can not be a value of a non-null type String
A String is guaranteed to hold a real string — never null. The compiler refuses to put null in
it. If you want to allow null, you say so explicitly with a ?:
val maybeName: String? = null // fine — String? can hold null
String and String? are different types. The first can never be null; the second might be.
And here is the payoff — the compiler will not let you use a String? as if it were definitely
there:
val maybeName: String? = getName()
val length = maybeName.length // error: only safe (?.) or non-null asserted (!!.) calls allowed
The compiler stops you at compile time, forcing you to handle the "what if it is null?" case before the program can even run. The crash that Java discovers in production, Kotlin discovers while you type. That is the entire idea, and everything else in this module is how you satisfy the compiler cleanly.
Why this changes how you work
This is not merely a safety net; it changes the shape of your thinking:
- Absence becomes visible. When you see
String?in a function's signature, you know it can return nothing, and the compiler makes you deal with it. When you seeString, you know it never will. The type documents reality. - The check moves to the boundary. You handle null once, where the value enters your program (user input, a network response, a database row), and everything inside works with guaranteed non-null types. No defensive checks scattered everywhere "just in case".
- A whole category of crash largely disappears. NPEs do not vanish entirely — you can still
force one with
!!(the last lesson of this module), and Java code you call can hand you null — but the accidental NPE, the one you did not see coming, is designed out.
The two types, side by side
The mental model to carry through the module:
var a: String = "Pune"
a = null // compile error — String cannot be null
var b: String? = "Pune"
b = null // fine — String? is allowed to be null
println(a.length) // fine — a is guaranteed non-null
println(b.length) // compile error — b might be null, you must handle it
Every type has a nullable partner: Int?, Double?, Boolean?, List<String>?, and so on. The
? is a promise-breaker: it says "I might not be here, so you must check before you use me". The
absence of ? is a promise: "I am always here".
Where null legitimately comes from
Nullable types are not a nuisance to avoid — they model something real. A value is genuinely sometimes absent:
- User input —
readLine()returnsString?because there might be no input. - A search that finds nothing — "the user with this email" might not exist.
- An optional field — a customer might have no middle name, no email, no alternate phone.
- A network or database result — the row might not be there.
Kotlin makes you represent "sometimes absent" honestly, as String?, rather than pretending it is
always present and crashing when it is not. A nullable type is you telling the truth about your
data. The next lessons are the tools for working with that truth cleanly — the safe call, the
Elvis operator, let, and smart casts — so that handling null is a pleasure rather than a chore.
Check your work
What Tony Hoare called the null reference. His "billion-dollar mistake".
Why null causes so many crashes in languages like Java. Any reference can be null, the compiler does not force a check, so code assuming a value crashes at runtime with an NPE.
Kotlin's core fix. Make "can be null" part of the type, and let the compiler enforce the check.
The difference between String and String?. String can never hold null; String? might —
they are different types.
What the compiler does with maybeName.length on a String?. Refuses it at compile time until
you handle the null case.
When Kotlin catches the null bug versus when Java does. Kotlin at compile time (as you type); Java at runtime (in production).
How the check moves. To the boundary where the value enters — handle it once, work with non-null types inside.
Whether NPEs are impossible in Kotlin. No — !! and Java interop can still produce them — but
the accidental NPE is designed out.
What a nullable type really models. A value that is genuinely sometimes absent — telling the truth about your data.
Practice
- Declare
val name: String = nulland read the exact compiler error. - Change it to
String?and confirm null is now allowed. - Declare a
String?, try to call.lengthon it directly, and read the error the compiler gives. - Write a function
fun findCity(pincode: String): String?that returns a city for"411038"and null otherwise. Note how the?in the return type warns every caller. - List three values in an app you use that are genuinely "sometimes absent", and write the Kotlin
type for each (for example, a middle name is
String?). - Explain, in one sentence to a friend, why
StringandString?being different types prevents crashes. - Recall the last time an app you used crashed or misbehaved. Consider whether "a value was unexpectedly missing" could have been the cause.
Official documentation
- Kotlin — Null safety — The whole feature, from the language's authors.
- Kotlin — Null safety (tour) — A gentler walkthrough with a runnable playground.
- Tony Hoare — "Null References: The Billion Dollar Mistake" — The talk the phrase comes from.
Next: nullable types and the safe call operator, in full.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship