Skip to content
Null Safety Patterns
step 1/6

Reading — step 1 of 6

Learn

~1 min readNull Safety in Practice

Kotlin's type system tracks nullability. String cannot be null; String? can be.

Operators for working with nullables:

val s: String? = maybeName()

// Safe call — returns null if receiver is null
val len: Int? = s?.length

// Elvis — provide default
val len: Int = s?.length ?: 0
val len: Int = s?.length ?: throw IllegalStateException("no name")

// Not-null assertion (use sparingly — throws NPE on null)
val len: Int = s!!.length

// Safe cast
val x: String? = obj as? String

Smart casts — once you check, the type narrows:

fun describe(x: Any?): String {
    if (x == null) return "nothing"
    if (x is String) return "string of length ${x.length}"   // x is String here
    return "other"
}

let for null-safe transforms:

// Run block only if non-null
name?.let { processName(it) }

// Transform with null propagation
val upper: String? = name?.let { it.uppercase() }

requireNotNull / checkNotNull for asserting at API boundaries:

fun processUser(user: User?) {
    val u = requireNotNull(user) { "user must not be null" }
    // u is now non-null
}

The Default Map.getValue throws on missing keys — useful when your type system can guarantee presence.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…