ReviseAlgo Logo

Control Flow

switch-case

Compare legacy switch statements with modern switch expressions, covering arrows, yield, yield exhaustiveness, and pattern matching.

Interview: Focuses on the differences between statements and expressions, break-less fallthroughs, and compiler exhaustiveness requirements.

Last Updated: June 13, 2026 12 min read

The switch structure in Java evaluates an expression and transfers control to corresponding case labels. Java has evolved significantly in this area, transitioning from legacy Switch Statements (which can suffer from dangerous fallthrough errors) to modern Switch Expressions (which return values directly, enforce exhaustiveness, and eliminate the need for verbose break keywords).

Core Idea

Switch statements branch execution across multiple discrete values. Expressions yield a direct evaluation value from the chosen branch.

Why It Matters

Switch expressions enforce compile-time exhaustiveness. This ensures that adding a new enum value or sealed class type immediately flags unhandled branches.

Interview Lens

Expect deep checks on fallthrough loops, valid switch data types, yield rules, and pattern matching syntax.

Allowed Switch Types

A switch can evaluate expressions of the following types:

  • Primitives: byte, short, char, int (and their corresponding wrapper classes).
  • Enumerated types (enums).
  • String class objects (since Java 7).

Note that long, float, double, and boolean are strictly prohibited in standard switches because float precisions are unstable and boolean is better handled via if-else statements.

Statement vs Expression Switch

Java 14 introduced standard Switch Expressions, adding key syntactic improvements over legacy statements:

Feature Legacy Switch Statement Modern Switch Expression
syntax Uses colon (case X:) Uses arrow (case X ->)
Break statement Mandatory to prevent fallthrough No break needed; no fallthrough occurs
Yields Value No. Side-effects only. Yes. Evaluates to a value directly.
Exhaustiveness Not checked (leads to unhandled states) Strictly checked at compile time
Block values N/A Uses yield in multi-statement cases

Exhaustiveness Rules

When a switch is used as an expression (returns a value), the compiler requires that every possible input value must match a case label. If evaluating an enum, all enum constants must be listed, or a default label must be supplied. If switching on general types (like int or String), a default label is always mandatory.

Common Pitfalls

  • NullPointerExceptions (NPE): Passing a null reference to a switch statement causes a runtime NPE. This is because the JVM implicitly attempts to evaluate the object reference type or value. (Note: Java 21 permits an explicit case null label to handle this gracefully).
  • Accidental Fallthrough: Forgetting a break statement inside a colon-based legacy switch case block causes execution to fall through into subsequent case statements.
  • Mixing syntax: Attempting to mix arrow syntax (->) and colon syntax (:) in the same switch statement triggers compilation failures.

Best Practices

  • Prefer modern arrow-syntax switch expressions over colon-based switch statements to avoid fallthrough bugs.
  • Make switch expressions exhaustive to leverage the compiler's warning pipeline for future code modifications.
  • Perform explicit null validation on the switched variable prior to evaluating the switch block.

Interview-Relevant Information

Q1: What is 'yield' in Java switch expressions?
Answer: The yield keyword was introduced in Java 13/14 to return a value from a multi-statement block within a switch expression case. It acts similarly to return but is local to the switch block itself rather than exiting the entire method.

Q2: Why does switch on null fail?
Answer: The JVM performs reference dereferencing or calls methods like hashCode() or equals() on the switched variable. If it evaluates to null, a NullPointerException is thrown.

Quick Checklist

Can you distinguish statements from expressions, prevent switch fallthroughs, enforce exhaustiveness checks, write yields inside block cases, and handle null variables? If yes, you understand switch structures.

Use Cases

Constructing mapping logic converting status codes or enum states directly into printable labels or values.

Consolidating command dispatch blocks cleanly without nesting multiple layer block checks.

Common Mistakes

Accidentally omitting default branches on switch expressions with non-enum inputs, triggering compile errors.

Passing nullable instances into switch expressions without prior null guard safety validation.