🔀 Control Flow · Beginner

Switch expressions in Java

Arrow labels, no fall-through, yield, exhaustiveness.

🧩 The mysteryWhat if switch could just *answer* you: hand back a value, need no break, and refuse to compile if you forgot a case?

A switch that returns

Since Java 14, switch can be an expression: it produces a value you can assign or return. Note the semicolon after the closing brace, because the whole thing is part of an assignment statement.

String size = switch (n) {
    case 1, 2 -> "small";
    case 3 -> "medium";
    default -> "large";
};

Arrows never fall

An arrow label case X -> runs only its own arm. There is no fall-through, so no break is needed. Several values share an arm with commas: case 1, 2 ->.

int code = 2;
switch (code) {
    case 1 -> System.out.println("one");
    case 2 -> System.out.println("two");
    case 3 -> System.out.println("three");
} // prints only: two
🔮 Predict it

Your turn

n is 3. What prints?

int n = 3;
String r = switch (n) {
    case 1 -> "one";
    case 2, 3 -> "few";
    default -> "many";
};
System.out.println(r);
  1. few
  2. few many
  3. many
  4. Compile error
Show the answer

few. 3 matches case 2, 3, that single arm produces the value, and the switch is done. Arrow arms never fall through.

yield: the value of a block arm

When an arm needs several statements, give it a { } block and finish with **yield value;** to hand back the result. You can't use return there: it would try to leave the whole method, which isn't allowed from inside a switch expression.

int pts = switch (grade) {
    case 'A' -> 4;
    case 'B' -> {
        System.out.println("ok");
        yield 3;
    }
    default -> 0;
};
⚠️ The trap

It must cover everything

A switch expression must be exhaustive: every possible input needs a result. For an int or char that means a default. For an enum, listing all its constants is enough. Miss a case and it's a compile error, not a runtime surprise.

int n = 5;
String r = switch (n) {
    case 1 -> "one";
    case 2 -> "two";
}; // compile error: no default
🔮 Predict it

Your turn

What happens here?

char g = 'B';
int pts = switch (g) {
    case 'A' -> 4;
    case 'B' -> 3;
};
System.out.println(pts);
  1. Prints 3
  2. Prints 0
  3. Compile error
Show the answer

Compile error. A char has 65,536 possible values and only two are covered. A switch expression with no default here isn't exhaustive, so it never even runs.

🤔 Think first

Old labels, new switch?

Can classic colon labels (case 6:) appear inside a switch *expression*?

Think about it, then reveal the answer

Yes. Colon labels still fall through, so case 6: case 7: yield "weekend"; works: execution falls from 6 into 7, and **yield both produces the value and leaves the switch**. Arrows are usually cleaner, though.

💼 In the real world

In real projects

Exhaustiveness is a safety net. Add a new constant to an enum (say a new payment type) and every switch expression that forgot it stops compiling, instead of silently doing nothing in production. That's a big reason modern Java code prefers switch expressions.

Key takeaways

  1. case 1, 2 -> "small"; runs only that arm, no break needed
  2. In a { } block arm, yield value; produces the result
  3. Must cover every value: usually with default (or all enum constants)
  4. The whole switch expression ends with a semicolon when assigned

💡 A switch expression is a vending machine: press a button (the value) and exactly one item comes out, and every button must give something.

🤯 Did you know?

In Java 12's preview, switch expressions returned values with break "value";. Java 13 replaced that with the brand-new word yield, and the feature became final in Java 14.

Practice questions

What does this print?

int n = 2;
String r = switch (n) {
    case 1 -> "one";
    case 2 -> "two";
    case 3 -> "three";
    default -> "many";
};
System.out.println(r);
  1. two three many
  2. two
  3. many
  4. Compile error
Check your answer

two. n is 2, so the expression evaluates to "two". Arrow arms never fall through.

What does this print?

int n = 5;
String r = switch (n) {
    case 1 -> "one";
    case 2 -> "two";
};
System.out.println(r);
  1. null
  2. Compile error
  3. An empty line
  4. Throws MatchException
Check your answer

Compile error. A switch expression must produce a value for every possible int. With no default it isn't exhaustive, so the compiler rejects it.

Next: can you switch on a String? A long? A null? One of these crashes at runtime.