# Kotlin Switch: Implementing Switch-Case Functionality with the `when` Expression

> Learn how to implement switch case logic in Kotlin using the versatile when expression. Discover its powerful features like exhaustive checking and smart casts for efficient code.

- Repository: [JetBrains/kotlin](https://github.com/jetbrains/kotlin)
- Tags: how-to-guide
- Published: 2026-02-13

---

**Kotlin does not provide a traditional `switch` keyword; instead, it offers the powerful `when` expression, which serves as a type-safe replacement with support for exhaustive checking, smart casts, and flexible pattern matching.**

If you are searching for **kotlin switch** functionality, you will find that the JetBrains/kotlin repository implements control flow through the versatile `when` construct. This expression functions as both a statement for side effects and an expression that returns values, while integrating deeply with Kotlin's type system to provide compile-time safety.

## Understanding the Kotlin Switch Alternative

Unlike C-style languages that rely on the `switch` keyword, Kotlin's `when` expression provides a more robust solution for multi-way branching. As implemented in the compiler's frontend and IR pipelines, `when` can operate as an **expression** that yields a value or as a **statement** that performs side effects.

The construct supports two distinct forms: one with an explicit subject (`when (x) { ... }`) and one without (`when { ... }`), giving developers flexibility in how they structure conditional logic.

## Kotlin Switch Syntax: Subject and Condition Forms

### Subject-Based `when` (Traditional Switch Style)

When you provide a subject, `when` compares the subject's value against branch conditions sequentially. This form closely resembles traditional switch-case statements but eliminates fall-through behavior.

```kotlin
val day = 3
when (day) {
    1 -> println("Monday")
    2 -> println("Tuesday")
    3 -> println("Wednesday")
    else -> println("Another day")
}

```

### Subjectless `when` (Flexible Boolean Conditions)

Omitting the subject allows you to write arbitrary boolean expressions as branch conditions. This is particularly useful for range checks or complex condition combinations that would be cumbersome in a traditional switch statement.

```kotlin
val score = 87
val grade = when {
    score >= 90 -> "A"
    score >= 80 -> "B"
    score >= 70 -> "C"
    else -> "F"
}
println("Grade: $grade")

```

## Kotlin Switch Branch Types and Pattern Matching

The `when` expression supports multiple branch types, enabling sophisticated pattern matching beyond simple value equality.

### Value Matching and Collections

Branches can match single values, multiple values combined with commas, or check membership in collections using the `in` and `!in` operators.

```kotlin
val x = 10
when (x) {
    0, 1 -> println("Binary digit")
    in 2..9 -> println("Single digit")
    !in 0..99 -> println("Double digit or more")
    else -> println("Other")
}

```

### Type Checking with Smart Casts

Using the `is` and `!is` operators, `when` branches can check types and automatically cast the subject to that type within the branch. This **smart cast** functionality is implemented in the compiler's FIR and IR layers, specifically in [`WhenEntry.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenEntry.kt) and [`WhenBranchOptimiserLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenBranchOptimiserLowering.kt).

```kotlin
fun describe(value: Any) = when (value) {
    is String -> "String of length ${value.length}"
    is Int    -> "Integer $value"
    else      -> "Unknown type"
}
println(describe("Kotlin"))

```

### Exhaustiveness Checking for Enums and Sealed Classes

When the subject is an **enum** or **sealed** type, the Kotlin compiler verifies that all possible cases are covered. This exhaustiveness checking is handled by [`WhenChecker.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenChecker.kt) in the frontend, with diagnostic reporting centralized in [`WhenMissingCase.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenMissingCase.kt). If a branch is missing, the compiler emits a diagnostic error, ensuring type-safe control flow without requiring an `else` branch.

```kotlin
sealed class Result
data class Success(val data: String) : Result()
object Failure : Result()

fun handle(result: Result) = when (result) {
    is Success -> "Got ${result.data}"
    Failure    -> "Operation failed"
}   // No 'else' needed – compiler verifies exhaustiveness

```

## Kotlin Switch Implementation in the Compiler

The **kotlin switch** functionality is deeply integrated into the compiler's architecture. In the FIR (Frontend Intermediate Representation) layer, [`WhenEntry.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenEntry.kt) represents individual branches of a `when` expression. During IR (Intermediate Representation) lowering, [`WhenBranchOptimiserLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenBranchOptimiserLowering.kt) optimizes branch conditions and eliminates dead code.

The exhaustiveness analysis that makes `when` safer than traditional switch statements is implemented in [`WhenChecker.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenChecker.kt), which traverses the control flow graph to ensure all possible values of sealed classes and enums are handled. Diagnostic reporting for missing cases is centralized in [`WhenMissingCase.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenMissingCase.kt).

## Summary

- Kotlin replaces the traditional **switch** statement with the more powerful **`when` expression**.
- `when` functions as both an **expression** (returning values) and a **statement** (executing side effects).
- The construct supports **subject-based** and **subjectless** forms for flexible condition checking.
- Advanced features include **smart casts** with `is` checks, **collection membership** with `in`/`!in`, and **exhaustiveness checking** for sealed classes and enums.
- Compiler implementation resides in [`WhenChecker.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenChecker.kt), [`WhenMissingCase.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenMissingCase.kt), [`WhenEntry.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenEntry.kt), and [`WhenBranchOptimiserLowering.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenBranchOptimiserLowering.kt) within the JetBrains/kotlin repository.

## Frequently Asked Questions

### Does Kotlin have a traditional switch statement?

No, Kotlin does not include a `switch` keyword. Instead, it provides the `when` expression, which offers equivalent functionality with additional features like smart casts, exhaustiveness checking, and the ability to handle arbitrary boolean conditions.

### Can Kotlin `when` be used as an expression?

Yes, `when` can function as an **expression** that returns a value, allowing you to assign the result directly to a variable. It can also be used as a **statement** when you only need to execute side effects like printing output.

### How does Kotlin enforce exhaustive `when` expressions?

The Kotlin compiler enforces exhaustiveness through [`WhenChecker.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenChecker.kt) in the frontend. When the subject of a `when` expression is a **sealed class** or **enum**, the compiler verifies that all possible cases are covered and emits a diagnostic error via [`WhenMissingCase.kt`](https://github.com/JetBrains/kotlin/blob/main/WhenMissingCase.kt) if any branch is missing.

### Is it possible to use `when` without a subject in Kotlin?

Yes, you can omit the subject to create a **subjectless** `when` expression. This form allows you to write arbitrary boolean expressions as branch conditions, making it ideal for range checks or complex logical combinations that would be difficult to express with a traditional switch statement.