Beginner 9 min readKotlin 2.0

Kotlin Null Safety — Nullable Types and Safe Operators

Kotlin's type system distinguishes nullable from non-nullable types at compile time, eliminating most NullPointerExceptions.

What You Will Learn

  • Nullable types with ?
  • Safe call operator ?.
  • Elvis operator ?:
  • Not-null assertion !!
  • Smart casts after null checks

Nullable vs Non-Nullable Types

By default, Kotlin types cannot be null. Add ? to allow null.

Nullable Types

kotlin
fun main() {
    val name: String = "Kotlin"   // cannot be null
    var nick: String? = null      // can be null

    println(name.length)   // always safe
    // println(nick.length)  // compile error!
    println(nick?.length)  // safe: prints null
    nick = "Guide"
    println(nick?.length)  // prints 5
}
Output
6 null 5

String cannot be null — the compiler guarantees it. String? can be null. Calling .length on String? directly is a compile-time error. Use ?. instead.

Beginner Tip: Think of ? as adding "or null" to the type. String is always a string. String? is a string or null.

Safe Call Operator ?.

?. calls a method only if the receiver is not null. Returns null otherwise.

Safe Call

kotlin
fun main() {
    val city: String? = null
    println(city?.uppercase())    // null
    println(city?.length)         // null

    val name: String? = "kotlin"
    println(name?.uppercase())    // KOTLIN
    println(name?.reversed())     // niltok
}
Output
null null KOTLIN niltok

When city is null, ?. short-circuits and returns null without calling uppercase(). When name is "kotlin", ?. calls the method normally.

Elvis Operator ?:

?: provides a fallback value when the left side is null.

Elvis Operator

kotlin
fun main() {
    val input: String? = null
    val length = input?.length ?: 0
    println(length)

    val name: String? = "Kotlin"
    val display = name ?: "Anonymous"
    println(display)

    val city: String? = null
    val city2 = city ?: "Unknown"
    println(city2)
}
Output
0 Kotlin Unknown

input?.length is null (input is null), so ?: returns 0. name is "Kotlin" (not null), so ?: returns "Kotlin". city is null, so ?: returns "Unknown".

Best Practice: Use ?: with a sensible default instead of null checks when you need a guaranteed non-null value.

Not-Null Assertion !!

!! converts a nullable type to non-nullable, throwing NullPointerException if the value is null.

!! Operator

kotlin
fun main() {
    val value: String? = "Hello"
    println(value!!.length)   // safe here — value is not null

    val risky: String? = null
    // println(risky!!.length)  // throws NullPointerException!
}
Output
5

value!! asserts that value is not null. Since it is "Hello", .length works fine. If value were null, it would throw KotlinNullPointerException at runtime.

Common Mistake: Avoid !! in production code — it defeats null safety. Prefer safe calls, Elvis, or explicit null checks.

Smart Casts

After a null check, Kotlin automatically treats the variable as non-nullable.

Smart Cast

kotlin
fun greet(name: String?) {
    if (name != null) {
        // name is smart-cast to String (non-nullable) here
        println("Hello, ${name.uppercase()}!")
    } else {
        println("Hello, Guest!")
    }
}

fun main() {
    greet("Juned")
    greet(null)
}
Output
Hello, JUNED! Hello, Guest!

Inside the if (name != null) block, the compiler knows name cannot be null, so it is treated as String. No ?. needed inside the block.

Practice Exercise

Exercisepredict output

What prints? val x: String? = null val y: String? = "Kotlin" println(x?.length ?: -1) println(y?.length ?: -1)

Quick Quiz

Quick Quiz

What does the safe call operator ?. return when the receiver is null?

Frequently Asked Questions

Related Tutorials

Last updated: 2026-05-01Kotlin 2.0

Written by KotlinGuide Editorial Team · Reviewed by KotlinGuide Technical Review