Back to Operators & Expressions
Q7Question 7 of 9

What is the difference between switch statement and switch expression?

Key Concepts
  • Switch statement (classic): executes code blocks, needs break to prevent fall-through
  • Switch expression (Java 14+): returns a value, uses arrow ->, no fall-through, must be exhaustive
  • Arrow syntax: case "SAVINGS" -> 8.5; replaces case + break, no fall-through
  • yield keyword returns a value from a switch expression block when you need multiple statements
  • Switch expressions must cover all possible values (exhaustive) or have a default
  • Pattern matching in switch (Java 21+): case Integer i -> ... matches types, not just constants

Definition

The switch statement executes code blocks and needs break. The switch expression (Java 14+) returns a value, uses arrows, has no fall-through, and must be exhaustive.

Two forms of switch:

DIAGRAM
- **Switch statement (classic).** Executes statements in matching case blocks. Fall-through by default: without `break`, execution continues into the next case. Does not return a value.
- **Switch expression (Java 14+).** Returns a value. Uses `->` arrow syntax. No fall-through. Must be exhaustive (cover all possible inputs or have a default). Use `yield` for multi-statement blocks.

A bank rate card. The switch statement is a clerk who reads the card, finds the matching row, and then keeps reading the next rows unless you tell them to stop (break). The switch expression is a smart card reader that finds the row, returns the rate, and stops automatically.

Understanding the Concepts

How does the classic switch statement work?

JAVA
String accountType = "SAVINGS";
double rate;

switch (accountType) {
    case "SAVINGS":
        rate = 4.0;
        break;         // without break, falls through to next case!
    case "CURRENT":
        rate = 0.0;
        break;
    case "FIXED_DEPOSIT":
        rate = 7.5;
        break;
    default:
        rate = 0.0;
        break;
}
System.out.println("Rate: " + rate);

Fall-through bug (forgetting break):

JAVA
// BUG: missing break on SAVINGS
switch (accountType) {
    case "SAVINGS":
        rate = 4.0;     // matched here
        // no break! falls through
    case "CURRENT":
        rate = 0.0;     // overwrites rate!
        break;
}
// rate is 0.0, not 4.0!

How does the switch expression work (Java 14+)?

JAVA
String accountType = "SAVINGS";

double rate = switch (accountType) {
    case "SAVINGS"       -> 4.0;
    case "CURRENT"       -> 0.0;
    case "FIXED_DEPOSIT" -> 7.5;
    default              -> 0.0;
};

System.out.println("Rate: " + rate);  // 4.0

No break needed. No fall-through possible. The arrow -> returns the value directly.

How does yield work for multi-statement cases?

JAVA
double rate = switch (accountType) {
    case "SAVINGS" -> 4.0;
    case "LOAN" -> {
        double base = 8.5;
        double margin = calculateMargin(creditScore);
        yield base + margin;  // yield returns the value from the block
    }
    default -> 0.0;
};

yield is like return but for switch expression blocks.

What types can switch operate on?

JAVA
// Classic: byte, short, char, int, String, enum
switch (dayOfWeek) { case MONDAY: ... }

// Switch expression: same types + pattern matching (Java 21+)
var result = switch (obj) {
    case Integer i  -> "Integer: " + i;
    case String s   -> "String: " + s;
    case null       -> "null";
    default         -> "Other: " + obj;
};

What does exhaustive mean?

Switch expressions must cover every possible value. The compiler enforces this.

JAVA
enum AccountType { SAVINGS, CURRENT, LOAN }

// This compiles: all enum values covered
String label = switch (type) {
    case SAVINGS -> "Savings";
    case CURRENT -> "Current";
    case LOAN    -> "Loan";
    // no default needed: all enum values handled
};

// This does NOT compile: missing LOAN
// String label = switch (type) {
//     case SAVINGS -> "Savings";
//     case CURRENT -> "Current";
// };  // COMPILE ERROR: not exhaustive

For String and int switches, you need a default because the compiler cannot enumerate all possible values.

What are common mistakes?

  • Forgetting break in classic switch. Causes fall-through bugs. Use switch expressions to eliminate this.
  • Forgetting default in switch expression on String/int. Must be exhaustive. Add default.
  • Null input. Before Java 21, switch on a null String/Integer throws NPE. Java 21+ adds case null.
  • Using switch for 2 values. If-else or ternary is simpler for 2 cases.

What should a senior engineer know?

  • Switch expressions can assign to final variables. final var rate = switch(...) {...}; is cleaner than declaring + assigning in if-else.
  • Pattern matching (Java 21+) replaces instanceof chains. case Account a when a.isActive() -> ... combines type check + guard.
  • Sealed classes + switch is exhaustive without default: if a sealed interface has 3 permitted subtypes and all are covered, no default needed.
  • Performance: switch on int/enum compiles to tableswitch or lookupswitch bytecodes, which are O(1). Switch on String uses hashCode + equals.

Visual Overview

DIAGRAM
  Classic switch statement:        Switch expression (Java 14+):
  switch (type) {                  var rate = switch (type) {
    case "SAVINGS":                   case "SAVINGS" -> 4.0;
      rate = 4.0;                     case "CURRENT" -> 0.0;
      break;  ← must remember!        default        -> 0.0;
    case "CURRENT":                 };  ← returns a value
      rate = 0.0;
      break;
    default:
      rate = 0.0;
  }

  Key differences:
    Fall-through:  statement YES (needs break)    expression NO
    Returns value: statement NO                    expression YES
    Exhaustive:    statement optional default      expression REQUIRED
    Arrow syntax:  statement uses :                expression uses ->

Key Takeaway

The classic switch statement executes code blocks and requires break to prevent fall-through. Forgetting break is one of the most common bugs in Java. The switch expression, introduced in Java 14, fixes this by returning a value, using arrow syntax with no fall-through, and requiring exhaustive coverage of all possible inputs.

Use switch expressions when you need to assign a value based on multiple cases. Use yield inside a block when a case needs multiple statements. And use pattern matching (Java 21+) to replace instanceof chains with type-matching cases.

One sentence to remember: switch expression uses arrows, returns a value, has no fall-through, and must be exhaustive – prefer it over the classic switch statement.

---

Share
Use ← → arrow keys to navigate