Contents

The arrow -> replaces the colon :. Arrow cases do not fall through, so break is never needed. Each arrow case can be a single expression, a block, or a throw.

// Old style — fall-through prone, verbose int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; default: throw new IllegalArgumentException("Unknown day: " + day); } // New style — switch expression with arrow syntax int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; }; // No default needed: Day is an enum — compiler checks exhaustiveness Arrow cases never fall through. If you need fall-through behavior for legacy reasons, stick to colon-style cases — but prefer arrow syntax for all new code.

When a case body is a block (not a single expression), use yield to return the value from the block. yield is a context-sensitive keyword — it only has meaning inside a switch expression block.

int result = switch (input) { case "one" -> 1; case "two" -> 2; case "three" -> 3; default -> { // block body — must use yield to produce the value System.out.println("Unknown input: " + input); yield -1; } }; // yield also works with colon-style cases (traditional syntax) int score = switch (grade) { case 'A': System.out.println("Excellent!"); yield 100; case 'B': yield 85; case 'C': yield 70; default: yield 0; }; yield is only valid inside a switch expression — not a switch statement. A switch expression MUST yield a value from every execution path (the compiler enforces this).

A switch expression (one that produces a value) must cover all possible values. For enums, the compiler checks that every constant is handled. For other types, a default or case null, default is required.

enum Season { SPRING, SUMMER, AUTUMN, WINTER } // Exhaustive — all 4 enum constants are covered, no default needed String activity = switch (season) { case SPRING -> "Gardening"; case SUMMER -> "Swimming"; case AUTUMN -> "Hiking"; case WINTER -> "Skiing"; }; // If you add a new enum constant (e.g., MONSOON) without updating // the switch, it becomes a compile-time error — not a silent runtime bug. // For String/int selectors — default is required String category = switch (statusCode) { case 200, 201 -> "Success"; case 400 -> "Bad Request"; case 401, 403 -> "Auth Error"; case 404 -> "Not Found"; case 500 -> "Server Error"; default -> "Unknown (" + statusCode + ")"; };

Multiple case labels can be combined on a single case using commas, both in arrow and traditional syntax:

// Multiple constants → same result String type = switch (ch) { case 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' -> "vowel"; default -> "consonant"; }; // Switch expression used directly as a method argument System.out.println(switch (month) { case JANUARY, MARCH, MAY, JULY, AUGUST, OCTOBER, DECEMBER -> 31; case APRIL, JUNE, SEPTEMBER, NOVEMBER -> 30; case FEBRUARY -> year % 4 == 0 ? 29 : 28; });

Switch expressions are most valuable for mapping a finite set of inputs to output values — enum constants to labels, status codes to categories, type tokens to behavior. The arrow form (case X -> result) is preferred for single-expression cases because it removes fall-through entirely and keeps each arm on one line. When a case requires multiple statements, use a block with yield to return the value. Combined with sealed classes, switch expressions become exhaustive type dispatch: the compiler verifies every subtype is handled and raises a compile error if you add a new subtype without updating the switch.

// HTTP status classifier record HttpStatus(int code, String phrase) {} String classify(int code) { return switch (code / 100) { case 1 -> "Informational"; case 2 -> "Success"; case 3 -> "Redirection"; case 4 -> "Client Error"; case 5 -> "Server Error"; default -> "Unknown"; }; } // Switch expression assigning to a var var description = switch (shape) { case Circle c -> "Circle with radius " + c.radius(); case Rectangle r -> "Rectangle " + r.width() + "x" + r.height(); default -> "Unknown shape"; }; // Nested switch expressions String priority = switch (severity) { case CRITICAL -> switch (environment) { case PRODUCTION -> "P0 - Page immediately"; case STAGING -> "P1 - Fix before release"; default -> "P2 - Fix soon"; }; case HIGH -> "P2 - Fix soon"; case MEDIUM -> "P3 - Schedule"; case LOW -> "P4 - Backlog"; }; Switch expressions can be used anywhere a value is expected — as a method argument, in a variable initializer, in a return statement, or even as the initializer of another switch.