skip to content

Not-Null Assertion !!

!! forces a nullable value to non-null and throws a NullPointerException when you are wrong. Interviewers ask about it to see whether you treat it as a deliberate, documented escape hatch or sprinkle it to silence the compiler.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What does the !! operator do in Kotlin, and what happens at runtime if the value is null?

level: juniorimportance: must knowfreq 80%

answer

  1. T? -> T, no runtime safety net
  2. throws NPE (KotlinNullPointerException) on null
  3. escape hatch out of null safety
  4. prefer ?. , ?: , or smart-cast
  5. one !! per line for clean stack traces

basics

~10 s

!! tells the compiler to treat a nullable value as if it is definitely not null. If the value actually is null at runtime, the program crashes with a NullPointerException.

solid answer

~40 s

The not-null assertion operator !! converts an expression of type T? to type T. It is the programmer asserting to the compiler 'trust me, this is not null'. If the value is non-null, the result is that value unchanged. If it is null, !! throws a NullPointerException (concretely a kotlin.KotlinNullPointerException, a subtype of java.lang.NullPointerException). It is an escape hatch out of Kotlin's null-safety guarantees: unlike ?. (safe call) or ?: (Elvis), it does not handle null gracefully — it fails loudly. Use it only when you have external knowledge the compiler lacks that a value cannot be null; otherwise prefer ?., ?:, or a smart-cast null check.

code

kotlin · 7 lines
kotlin
fun main() {
    val present: String? = "data"
    println(present!!.length)   // 4

    val missing: String? = null
    println(missing!!.length)   // throws NullPointerException here
}

go deeper

for a junior

Knows !! means 'not null' and that it crashes with an NPE if wrong; can pick ?. or ?: as a safer option.

for a middle

Explains it as a T?->T coercion, names KotlinNullPointerException, and articulates why it is an escape hatch versus smart casts.

for a senior

Frames !! as a deliberate invariant assertion, advises one-per-line for diagnosability, and contrasts it with require/checkNotNull for clearer failures.

for a principal

Discusses team policy (lint rules banning !!), how platform types and interop pressure people toward !!, and designing APIs so callers rarely need it.

## What `!!` is The **not-null assertion operator** `!!` takes a nullable expression of type `T?` and produces a value of the non-null type `T`. You are *asserting* (promising) to the compiler that the value is not null at that point. - `T?` means "a `T` or `null`" — a **nullable type**. - `T` (no `?`) means "definitely not null" — a **non-null type**. - `!!` is the bridge that forces `T?` into `T` without any runtime check on your part. ## Runtime behaviour ```kotlin val a: String? = "hi" val b: String = a!! // ok, b == "hi", length is 2 val x: String? = null val y: String = x!! // throws NullPointerException at this line ``` - If the value is **non-null**, `!!` returns it unchanged with type `T`. - If the value is **null**, `!!` throws a `NullPointerException`. In practice this is `kotlin.KotlinNullPointerException`, which **extends** `java.lang.NullPointerException`, so a `catch (e: NullPointerException)` will catch it. ## Why it is a code smell Kotlin's whole point is to push null handling into the type system so NPEs disappear. `!!` opts *out* of that. Compared with the alternatives: - `?.` (safe call) — returns `null` instead of crashing. - `?:` (Elvis) — supplies a fallback value. - `if (x != null) { ... }` — **smart cast** narrows `x` to non-null inside the block, no operator needed. `!!` does none of this — it just defers the crash to runtime. So it is acceptable only when you genuinely know more than the compiler (e.g. a framework guarantees a field is set after init) and a crash is the correct response to that invariant being violated. ## Diagnosability tip Put `!!` on its own statement rather than burying it in a long chain. `a!!.b!!.c!!` gives a stack trace pointing at the whole line; you cannot tell *which* `!!` threw. One assertion per line makes failures pinpointable.

  • What exact exception type does !! throw?
    kotlin.KotlinNullPointerException, which is a subclass of java.lang.NullPointerException, so it can be caught as a plain NullPointerException.
  • Name a safer alternative to x!!.foo() when x might be null.
    x?.foo() returns null instead of crashing, or x?.foo() ?: default to supply a fallback.

It is like signing a waiver that says 'I promise this isn't null' — if you're wrong, you take the fall (a crash) immediately.

saying these in an interview costs you the question

  • Says !! converts null into a default/empty value
  • Thinks !! is the normal/recommended way to handle nullables
  • Believes !! does a runtime check that returns null safely
  • Cannot name a single safer alternative (?., ?:)
  • Confuses !! with the boolean not operator !

context

open as a page

When would you choose !! over the safe-call ?. or the Elvis ?: operator, and what is the cost of choosing wrong?

level: middleimportance: must knowfreq 70%

basics

~20 s

Use !! only when you are certain a value can't be null and a crash is the right outcome if you're wrong. Use ?. or ?: when null is a real possibility you want to handle gracefully.

open as a page

Why is chaining multiple !! on one line (a!!.b!!.c) considered bad practice, and how does it affect debugging?

level: middleimportance: should knowfreq 45%

basics

~10 s

If you put several !! on one line and it crashes, the error only tells you the line number, not which !! actually failed. Splitting them out makes the failure point obvious.

open as a page

How do !! and platform types interact when calling Java from Kotlin, and why does Java interop drive overuse of !!?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Java values whose nullability Kotlin can't see are 'platform types'. Kotlin lets you use them without forcing null checks, so developers reach for !! to convert them to non-null — sometimes hiding real nulls and causing crashes later.

open as a page

When is !! genuinely justified, and how would you set a team policy and lint rules around it?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

!! is fine in narrow cases where a value is guaranteed non-null but the compiler can't see it, like right after a check or a framework-initialized field. As a team, ban it by default and require a comment or a clearer assertion when it's truly needed.

open as a page