skip to content

when as an Expression

when replaces switch and does far more: comma-grouped branches, arbitrary boolean conditions in the subjectless form, in-range checks, and is-checks that smart-cast the subject. It is one of the most-asked Kotlin constructs because idiomatic code leans on it constantly.

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

questions

5

What is Kotlin's `when` and how does it differ from a Java/C-style `switch`?

level: juniorimportance: must knowfreq 80%

answer

  1. No fall-through, no break
  2. else = default
  3. Statement or expression
  4. First matching branch wins, top to bottom
  5. Conditions can be expressions, not just constants

basics

~10 s

when is Kotlin's replacement for switch. You list conditions and pick the first matching branch. It can be used as a value-producing expression or as a plain statement, and branches don't fall through.

solid answer

~40 s

`when` matches a subject against branches `condition -> result`, running the first match. Unlike C/Java `switch`, there is no fall-through and no `break`; each branch is independent. `else` is the catch-all (like `default`). It works as a statement (ignore the result) or an expression (the matched branch's value becomes the result, so it must yield a value and be exhaustive). Branch conditions aren't limited to constants: you can use any expression, comma-group several values (`1, 2 ->`), match ranges with `in`/`!in`, and test types with `is`/`!is`. A branch body can be a block `{ ... }` whose last expression is its value. `when` evaluates branch conditions top to bottom and stops at the first true one.

code

kotlin · 6 lines
kotlin
fun describe(x: Int): String = when (x) {
    0 -> "zero"
    1, 2, 3 -> "small"
    in 4..9 -> "medium"
    else -> "large"
}

go deeper

for a junior

Knows when replaces switch, uses else, and that there is no fall-through.

for a middle

Explains statement vs expression use and that conditions can be ranges, types, or grouped values.

for a senior

Articulates exhaustiveness for the expression form and that when compiles to efficient jump tables.

for a principal

Discusses when to prefer when over polymorphism/sealed hierarchies for readability and how it interacts with exhaustiveness guarantees in API evolution.

## What `when` is `when` is Kotlin's multi-way branching construct, replacing the C/Java `switch`. The general form is: ```kotlin when (x) { 1 -> "one" 2, 3 -> "two or three" // comma-grouped branch in 4..10 -> "small" // range check else -> "other" // catch-all (like default) } ``` Each line is `condition -> body`. Kotlin evaluates the branch conditions **top to bottom** and executes the **first** one that matches, then stops. ## Key differences from `switch` - **No fall-through, no `break`.** In C/Java a `case` without `break` falls into the next one. Kotlin branches are isolated; you never write `break`. - **`else` instead of `default`** as the catch-all. - **Conditions are expressions, not just constants.** `switch` typically allows only compile-time constants. `when` branches can use ranges (`in 1..10`), type tests (`is String`), or — in the subjectless form — arbitrary boolean expressions. - **It can be an expression.** `val s = when (x) { ... }` assigns the matched branch's value. As a statement, you just run side effects and ignore the result. ## Statement vs expression - **Statement form:** result discarded; `else` is optional. - **Expression form:** the value of the chosen branch becomes the `when` value, so it must be **exhaustive** (every possibility covered, usually via `else`) and every branch must produce a value. ## Branch bodies A body can be a single expression or a block: ```kotlin val label = when (n) { 0 -> "zero" else -> { val sign = if (n > 0) "+" else "-" "$sign$n" // last expression of the block is the branch value } } ``` Under the hood `when` compiles to ordinary conditional jumps (or a `tableswitch`/`lookupswitch` for dense integer/enum subjects), so it's as efficient as a `switch`.

  • Do you need `break` between branches?
    No. Kotlin `when` has no fall-through, so `break` is neither needed nor allowed as a fall-through control; each branch is independent.
  • What value does a block-bodied branch produce?
    The value of the last expression in the block.

Like a receptionist scanning a checklist top to bottom and sending you to the first desk that fits — never to two desks at once.

saying these in an interview costs you the question

  • Claiming `when` falls through like `switch` without `break`
  • Thinking branch conditions must be compile-time constants
  • Saying you must always write `break`
  • Believing `when` can only be a statement, never an expression

context

open as a page

How do `is`/`!is` branches work in `when`, and how do smart casts apply inside those branches?

level: seniorimportance: must knowfreq 65%

basics

~20 s

is Type matches when the subject is that type; !is is the opposite. Inside an is branch Kotlin smart-casts the value to that type automatically, so you can call its members without an explicit cast.

open as a page

Explain comma-grouped branches and `in`/`!in` range checks in `when`. What does comma between conditions mean?

level: middleimportance: should knowfreq 55%

basics

~10 s

A comma between conditions means OR: the branch matches if any listed value matches. in range checks membership and !in checks non-membership, working with ranges, collections, or anything defining contains.

open as a page

What is the subjectless (argument-less) form of `when`, and when would you use it over an `if`/`else if` chain?

level: middleimportance: should knowfreq 60%

basics

~20 s

Write when {} with no value in the parentheses. Each branch is its own boolean condition, and the first true one wins. It reads more cleanly than a long if/else if chain when you have several unrelated conditions.

open as a page

What are the common correctness pitfalls when refactoring a long `if`/`else if` chain into `when`, particularly around branch order, equality, and side effects?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Branch order matters because the first match wins, so overlapping conditions can change behavior if reordered. Also remember when uses structural equality (==), evaluates the subject once, and stops at the first match — so don't rely on later branches' side effects.

open as a page