Start learning free

LESSON 91 OF 677 · CONDITIONAL STATEMENTS

Null safety: the ? in the type

Lesson

In Java, ANY variable can secretly be null — and your program only finds out when it crashes with the infamous NullPointerException. Kotlin was designed to kill that bug at compile time: a plain String can never hold null. When a value might be absent, you must say so in the type with a question mark — String? is a nullable type, and the compiler refuses to let you touch it until you have dealt with the null case.

var name: String = "Kotlin"
name = null                    // rejected at compile time!
var nickname: String? = null   // fine — the ? allows null

The assignment to name never even compiles:

error: null cannot be a value of a non-null type 'String'.

And you cannot call members on a String? directly — nickname.length gives:

error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'String?'.

Three ways past that error:

// 1. safe call ?. — the value, or null when absent (safe)
nickname?.length          // Int? : the length, or null

// 2. Elvis ?: — the value, or your fallback when null (safe)
nickname ?: "none"        // never null — always a real String

// 3. !! — "trust me, it's not null": the value, or CRASH (dangerous)
nickname!!.length         // throws if nickname is null

They chain nicely too: nickname?.length ?: 0 reads "the length if there is one, otherwise 0".


The trap:

!! silences the compiler — it does NOT make the value exist. This compiles without a single complaint:

val nickname: String? = null
println(nickname!!.length)   // "trust me"... but it IS null

...and dies the moment it runs:

Exception in thread "main" java.lang.NullPointerException

That is the exact crash Kotlin's type system exists to prevent — !! is you overriding the safety, which is why experienced Kotlin developers treat every !! as a code smell. The rule: reach for ?. and ?: by default, and use !! only when you can prove the value is there.


Assignment
Follow the Coding Tutorial and try all three on a present and an absent value:

  • declare val present: String? = "Kotlin" and val missing: String? = null,
  • print the length of each with the safe call ?.length — no crash, even for missing,
  • print each value with the Elvis fallback ?: "none",
  • print present!!.length — safe here, because present certainly holds a value.

The exact expected output is:

present length = 6
missing length = null
present or default = Kotlin
missing or default = none
forced length = 6

Hint
Build each line with a string template, e.g. println("present length = ${present?.length}"). Note that ${missing?.length} prints the word null — the safe call returned null, and the template prints it as text.


STEP 1 OF 7
    Ctrl + Enter to check