skip to content

What does the expression `name?.let { it.uppercase() } ?: "UNKNOWN"` do, and how does it handle a null `name`?

level: juniorimportance: must knowfreq 80%

answer

  1. ?. runs let only when non-null
  2. ?: supplies the fallback
  3. it is smart-cast to non-null inside let
  4. whole thing is one expression
  5. elvis fires if let also returns null

basics

~10 s

If name is not null, it runs the block and uppercases it. If name is null, the block is skipped and the whole expression becomes "UNKNOWN". The Elvis operator (?:) supplies the fallback.

solid answer

~40 s

`?.` is the safe-call operator: `name?.let { ... }` invokes `let` only when `name` is non-null, otherwise the whole `?.let{...}` short-circuits to `null`. Inside `let`, the receiver is passed as the lambda argument `it`, already smart-cast to the non-nullable type, so `it.uppercase()` is safe. The Elvis operator `?:` then says: if the left side is `null`, evaluate the right side instead. So a non-null `name` yields its uppercased value; a null `name` makes `?.let` produce `null`, and `?:` substitutes `"UNKNOWN"`. This is the canonical `?.let {} ?: default` pattern for transform-or-default on a nullable. It avoids an explicit `if (name != null)` check and keeps the value as a single expression.

code

kotlin · 5 lines
kotlin
fun greet(name: String?): String =
    name?.let { "Hello, ${it.uppercase()}" } ?: "Hello, stranger"

println(greet("ada"))   // Hello, ADA
println(greet(null))    // Hello, stranger

go deeper

for a junior

Reads the pattern correctly: block runs only when non-null, Elvis gives the default; knows it is the non-null value.

for a middle

Notes it is one expression usable as an initializer, and that the fallback also fires when the lambda returns null.

for a senior

Distinguishes 'name is null' from 'lambda returned null' and chooses the form deliberately; mentions smart-cast inside the block.

for a principal

Frames this as a readability/intent tradeoff vs. if/early-return, and flags the lambda-returns-null edge as a correctness hazard in code review.

## The operators involved - **`?.` (safe call):** `a?.b` evaluates to `a.b` when `a` is non-null, otherwise to `null` without throwing a `NullPointerException`. The whole chain short-circuits the moment a receiver is null. - **`let`:** a scope function. `x.let { block }` passes `x` into the lambda as the implicit parameter `it` and returns whatever the lambda returns. - **`?:` (Elvis):** `a ?: b` evaluates to `a` if `a` is non-null, otherwise to `b`. ## Putting them together ```kotlin val result: String = name?.let { it.uppercase() } ?: "UNKNOWN" ``` Step by step when `name: String?`: 1. If `name` is **non-null**, `?.` calls `let`. Inside the block `it` is `name` smart-cast to non-nullable `String`, so `it.uppercase()` compiles and runs. `let` returns that uppercased string, and `?:` leaves it untouched. 2. If `name` is **null**, `?.let { ... }` short-circuits to `null` (the lambda never runs). `?:` then yields the fallback `"UNKNOWN"`. ## Why use this instead of an if-check It is a single **expression**, so it can initialize a `val`, be returned directly, or be passed as an argument. The transformation (`uppercase()`) and the default both live in one place. ## A subtle trap If the lambda itself can return `null`, the Elvis branch also fires for that case: ```kotlin val r = map[key]?.let { transform(it) } ?: fallback // fallback also used if transform returns null ``` That is sometimes desired, sometimes a bug — be deliberate about it.

  • If `name` is `"ada"` but `it.uppercase()` somehow returned null, what would the expression yield?
    It would yield the Elvis fallback `"UNKNOWN"`, because `?:` fires whenever the left side is null — including when the lambda returns null, not only when `name` is null.
  • What is `it` here and what type does it have?
    `it` is the implicit single parameter of `let` — it is `name` smart-cast to the non-nullable type `String` inside the block.

Like a vending machine: insert a valid coin (non-null) and you get the snack transformed by the machine; insert nothing and the machine just hands back the default 'sold out' card.

saying these in an interview costs you the question

  • Saying the block still runs when name is null
  • Claiming ?. throws when the receiver is null
  • Confusing ?: (Elvis) with ?. (safe call)
  • Thinking it is nullable inside the let block
  • Not realizing the fallback also triggers if the lambda returns null

context