Skip to content

Chapter 2 of 7

Null Safety

Null safety is Kotlin's most celebrated feature, designed to eliminate NullPointerException at compile time. By default, types are non-nullable — declaring var name: String means the compiler will reject any attempt to assign null. To permit it, you append a question mark to declare a nullable type, as in String?. Once a type is marked nullable, the compiler tracks every place it is used and forces you to handle the null case explicitly, transforming what was a runtime hazard in languages like Java into a compile-time verification.

Three operators form the everyday vocabulary of null handling. The safe call operator ?. accesses a property or calls a method on a nullable receiver, but if the receiver is null, the entire expression short-circuits to null instead of throwing. For example, user?.address?.city returns null if user or address is null, and you can chain as many ?.'s together as needed — each short-circuits independently. To provide a default value when the left side is null, the Elvis operator ?: supplies an alternative: name?.length ?: 0 falls back to 0 whenever name is null. The right-hand side of ?: is evaluated only when needed, which makes the operator ideal for lazy fallbacks, and because it is right-associative with low precedence, idioms like a ?: b ?: c cleanly find the first non-null value. For situations where you are certain a value is non-null, !! casts it to non-null but throws a KotlinNullPointerException if that certainty proves wrong — used sparingly because it is a runtime escape hatch whose stack trace points to the !! site.

You can also check for null directly with == or != against null, and the compiler will smart cast the variable inside the conditional block, so it can be used as non-null without any operator at all. Combined with let, this yields an idiomatic null check: name?.let { println(it) } executes the block only when name is non-null, with the lambda's last expression as the result; if name is null, the whole let call returns null. Because let returns the lambda result while also returns the original object, the two are distinct tools for different needs — choose also when you want the receiver to flow through a chain unchanged, and let when you want a computed transformation.

When Kotlin calls Java, it encounters nullable types whose nullability is not annotated. These become platform types (sometimes shown as String! in tooling) and are treated as both nullable and non-nullable by the compiler — effectively shifting null-safety responsibility to the caller. To restore compile-time guarantees, you can annotate Java declarations with @NotNull and @Nullable (from JetBrains, JSR-305, or AndroidX), after which Kotlin enforces them like any native nullable type. Finally, throwing an exception produces a Nothing, which by being a subtype of every type lets you write val name = input ?: throw IllegalArgumentException("name required") without further typing noise.

All chapters
  1. 1Foundations — Types, Variables, and Expressions
  2. 2Null Safety
  3. 3Classes, Objects, and Inheritance
  4. 4Functions, Lambdas, and Scope Functions
  5. 5Properties and Delegation
  6. 6Collections, Sequences, and Strings
  7. 7Coroutines and Flow

Drill it

Reading is not remembering. These come from the Kotlin Programming deck:

Q

What is null safety in Kotlin?

Null safety is a Kotlin feature that eliminates NullPointerException at compile time.By default, variables cannot hold null. You must explicitly declare a type...

Q

How do you declare a nullable type in Kotlin?

Append a ? to the type declaration:var name: String? = nullWithout the ?, the compiler will reject any attempt to assign null.

Q

What is the safe call operator in Kotlin?

The safe call operator ?. allows you to access a property or call a method on a nullable object without risking a NullPointerException:val length = name?.length...

Q

What is the Elvis operator in Kotlin?

The Elvis operator ?: provides a default value when an expression is null:val len = name?.length ?: 0If the left side is null, the right side is used.