The switch Statement and switch Expression in Java
The switch in Java dispatches on a value. It used to be a clunky statement with fall-through bugs; modern Java turned it into a safer, more expressive construct that also works as an expression.
The classic switch statement
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Unknown");
}
The break is critical. Without it, execution falls through to the next case β the classic bug source:
switch (day) {
case 1:
System.out.println("Monday");
// forgot break
case 2:
System.out.println("Tuesday"); // also prints when day == 1!
break;
}
Intentional fall-through
Sometimes fall-through is what you want β group several cases that share an action:
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("Weekday");
break;
case 6:
case 7:
System.out.println("Weekend");
break;
}
Switch expression (Java 14+)
The modern switch is an expression β it returns a value. No fall-through, no break, no surprises.
String label = switch (day) {
case 1, 2, 3, 4, 5 -> "Weekday";
case 6, 7 -> "Weekend";
default -> "Unknown";
};
Arrow syntax (->) takes a single expression or a block. With a block, use yield to return a value:
int monthDays = switch (month) {
case 4, 6, 9, 11 -> 30;
case 2 -> {
boolean leap = isLeapYear(year);
yield leap ? 29 : 28;
}
default -> 31;
};
Switch on String
String command = "help";
switch (command) {
case "start" -> start();
case "stop" -> stop();
case "help", "?" -> showHelp();
default -> System.out.println("Unknown command");
}
Case-sensitive. Internally uses hashCode + equals, so it's O(1) β faster than a chain of ifs.
Switch on enum
With enums, you don't qualify the constants:
enum Status { ACTIVE, IDLE, STOPPED }
Status s = Status.ACTIVE;
String msg = switch (s) {
case ACTIVE -> "Running";
case IDLE -> "Waiting";
case STOPPED -> "Offline";
};
Beauty of the switch expression on an enum: if you later add a FAILED constant, the compiler forces you to handle it. No default needed β exhaustiveness is checked.
Pattern matching (Java 21+)
Java 21 made switch even more powerful with pattern matching:
Object obj = 42;
String description = switch (obj) {
case Integer i when i > 0 -> "Positive int: " + i;
case Integer i -> "Non-positive int: " + i;
case String s -> "String of length " + s.length();
case null -> "null";
default -> "Something else";
};
The when clause adds a guard; null is now a real case. This replaces long chains of instanceof + cast.
Switch with sealed types
Combined with sealed interfaces, you get exhaustive case analysis:
sealed interface Shape permits Circle, Square, Triangle {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}
record Triangle(double base, double height) implements Shape {}
double area = switch (shape) {
case Circle c -> Math.PI * c.r() * c.r();
case Square sq -> sq.side() * sq.side();
case Triangle t -> 0.5 * t.base() * t.height();
};
// No default needed β compiler knows all subclasses
Switch vs if-else
| Use switch when... | Use if-else when... |
|---|---|
| Comparing one value against many constants | Conditions involve different variables |
| Enum or small set of values | Range checks (x > 10, s != null) |
| Need compiler exhaustiveness check | 2-3 simple conditions |
| Pattern matching on type | Complex boolean logic |
Common mistakes
- Missing
breakin a statement-style switch. - Mixing arrow and colon syntax in the same switch β not allowed.
- Empty
defaultβ remove it unless it really does nothing on purpose. - Expecting switch on
Objectbefore Java 21 β it only supports primitives, wrappers, String, enum, and (since 21) any type via pattern matching.
Modern recommendation
For new code on Java 14+, prefer the switch expression with arrow syntax. It's safer, shorter, and the compiler enforces exhaustiveness. Reach for if-else only when conditions involve different expressions or ranges.
Switch has gone from Java's dustiest feature to one of its most expressive constructs β take advantage of the modern form.