How does a switch expression differ from a switch statement, and when would you choose each?
answer
- Statement = action, no value; Expression = value
- Expression must be exhaustive; statement need not
- Context decides which one it is
- Both can use arrow syntax
- Refactor 'assign-in-each-case' statement into an expression
basics
~10 sA switch statement does an action and returns nothing; a switch expression computes and returns a value. Use the expression to assign or return a result; use the statement for pure side effects.
solid answer
~50 sA switch *statement* executes side effects and yields no value — historically with colon labels, break, and fall-through. A switch *expression* evaluates to a value you can assign or return, typically with arrow labels and no fall-through. The key differences: the expression must be exhaustive (cover all inputs) because it must produce a value, while the statement need not be; the expression uses 'yield' for block branches whereas the statement uses ordinary statements; and the expression composes anywhere a value is expected. Choose a switch expression when you are mapping an input to a result — it is safer (no accidental fall-through) and the compiler checks coverage. Choose a switch statement when each case performs distinct side effects (logging, dispatching) and there's no single value to return. Both can use arrow syntax, so you don't lose fall-through safety by picking the statement form.
go deeper
Knows the expression returns a value and the statement does not, and can pick the right one for a simple assign-vs-act case.
Lists the concrete differences (exhaustiveness, yield, fall-through) and refactors a value-building statement into an expression.
Explains that context (not syntax) determines the form, weighs side-effect vs value-mapping use, and consistently uses arrow form to avoid fall-through.
Defines code conventions for switch usage across the codebase and reasons about readability/maintainability tradeoffs when migrating legacy colon switches.
## Two constructs, one keyword The word `switch` introduces two different things depending on how you use it: - A **switch statement** — performs actions, produces *no* value. - A **switch expression** — evaluates to a *value*. This is the same distinction as between `if (...) { ... }` (statement) and the ternary `cond ? a : b` (expression). ## Switch statement Used for side effects. It does not need to cover all inputs and may simply do nothing for unmatched values: ```java switch (event) { // statement: no value case CLICK -> handleClick(); case HOVER -> handleHover(); // no default needed; other events ignored } ``` The classic colon form (with `break` and fall-through) is also a statement and remains valid, but the arrow form above is preferred for safety. ## Switch expression Used to compute a value. It must be **exhaustive** and produces a result via the branch expression or `yield`: ```java String label = switch (event) { // expression: yields a String case CLICK -> "clicked"; case HOVER -> "hovering"; default -> "unknown"; }; ``` ## The differences side by side | Aspect | switch statement | switch expression | |---|---|---| | Produces a value | No | Yes | | Exhaustiveness required | No | Yes | | Value from block branch | n/a | `yield` | | Typical use | side effects, dispatch | map input → result | | Fall-through (colon form) | possible | discouraged; arrow has none | ## How the compiler tells them apart The **context** decides. If the `switch (...) { ... }` appears where a value is needed — right side of an assignment, a `return`, a method argument — it is an expression. If it stands alone as a statement, it is a statement. The same arrow syntax serves both. ## Choosing between them - Reach for a **switch expression** whenever you are translating an input into an output value. You gain compiler-checked exhaustiveness and zero fall-through risk, and the code reads as a clean mapping. - Reach for a **switch statement** when each case *does something* (side effects) and there is no natural single value to return. Prefer the arrow form here too, so you still avoid fall-through. A common refactor is turning a value-building switch statement (declare variable, assign in each case, `break`) into a switch expression assigned once — shorter and safer.
- Can the same arrow syntax be used for both forms?Yes. Arrow labels work in both switch statements and switch expressions; the difference is whether the construct appears in a value-needing context (expression) or stands alone (statement).
- Give a refactor that benefits from switching to an expression.A statement that declares a result variable and assigns it in every case with break becomes a single 'var result = switch(...) {...};' — eliminating the mutable variable, the breaks, and gaining exhaustiveness checks.
saying these in an interview costs you the question
- Saying only expressions can use arrow syntax (statements can too)
- Claiming a switch statement must be exhaustive (it need not)
- Forcing a value out of a statement instead of using an expression
- Believing the two are syntactically distinguished rather than context-distinguished