1. What’s new in switch
If you wrote Java before version 14, switch looked roughly like this:
switch (day)
{
case MONDAY:
System.out.println("Start of the week!");
break;
case FRIDAY:
System.out.println("Friday, hooray!");
break;
default:
System.out.println("A regular day.");
break;
}
Looks fine, but:
- You must not forget break (otherwise you’ll “fall through” to the next case).
- Lots of repetitive code.
- If you want to return a value, you have to declare a variable beforehand and assign to it inside each case.
Java 14+ decided: enough of that! Time to make switch more convenient and modern.
Key new features:
- Switch became an expression, not just a statement — it can now return a value.
- New arrow syntax -> instead of colons and break.
- Multiple case labels separated by commas — for shared logic.
- The compiler checks that all cases are handled (especially with enum).
- No risk of fall-through — now it’s only possible explicitly.
2. Syntax of switch expressions
switch (value)
{
case A, B -> result1;
case C -> {
// multiple actions
yield result2;
}
default -> defaultResult;
}
-> and
yield
Basic example
Let’s get straight to it. Here’s how you can now return a value from a switch:
DayOfWeek day = DayOfWeek.MONDAY;
String message = switch (day)
{
case MONDAY, FRIDAY, SUNDAY -> "Short week or a day off!";
case TUESDAY -> "Tuesday is a tough day.";
case WEDNESDAY, THURSDAY -> "Midweek!";
case SATURDAY -> "Hooray, Saturday!";
// default is required if not all options are handled
default -> "Some kind of strange day...";
};
System.out.println(message);
What’s happening here:
- switch (day) is an expression that returns a value.
- After the arrow -> you specify the result for that case.
- You can group several case labels with commas.
- No break at all — Java knows where a branch ends.
- You can immediately assign the result to the message variable.
Example with numbers
int code = 404;
String result = switch (code)
{
case 200 -> "OK";
case 400, 404 -> "Client error";
case 500 -> "Server error";
default -> "Unknown code";
};
System.out.println(result);
Example with strings
String command = "start";
String status = switch (command)
{
case "start" -> "Starting!";
case "stop" -> "Stopping!";
case "pause" -> "Pause...";
default -> "Unknown command";
};
System.out.println(status);
Using a block with yield
Sometimes you want to perform several actions for a single case (for example, compute something complex or do logging). For this, you can use a block { ... } and the yield keyword:
int n = 7;
String parity = switch (n % 2)
{
case 0 -> "Even";
case 1 ->
{
System.out.println("Detected an odd number: " + n);
yield "Odd";
}
default -> "Something strange";
};
System.out.println(parity);
Important: inside the block you must have yield, which returns the value for that case.
3. Advantages of the new syntax
No need for break
In the classic switch, a forgotten break is a source of pain and mysterious bugs. In the new syntax, break isn’t needed at all: each branch ends automatically.
The compiler checks that all cases are handled
If you use an enum and haven’t handled all values, the compiler won’t let you build without default. This makes the code more reliable.
No “fall-through”
In the classic switch, if you forget break, execution will “fall through” to the next case. In the new syntax this is impossible (unless you use a block with statements and explicitly write break — but here it isn’t needed).
More compact and readable code
See for yourself:
Before:
String result;
switch (status) {
case "OK":
result = "Everything is fine";
break;
case "ERROR":
result = "Error";
break;
default:
result = "Unknown";
break;
}
After:
String result = switch (status) {
case "OK" -> "Everything is fine";
case "ERROR" -> "Error";
default -> "Unknown";
};
Multiple case labels — same logic
case MONDAY, FRIDAY, SUNDAY -> "A day off or a short day!";
4. Comparison with the classic switch
| Feature | Classic switch | New switch |
|---|---|---|
| break required | Yes | No |
| Fall-through | Yes | No |
| Can return a value | No (only via a variable) | Yes (expression) |
| Multiple cases separated by commas | No | Yes |
| Checks all cases | No | Yes (especially with enum) |
| Compactness | Lots of code | Short and clear |
| Use with enum and strings | Yes | Yes |
5. Compatibility with enum and strings
Example with enum
Suppose we have an enumeration:
enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Use it in the new switch:
DayOfWeek today = DayOfWeek.WEDNESDAY;
String mood = switch (today)
{
case MONDAY -> "Hard to get up...";
case FRIDAY -> "Weekend is near!";
case SATURDAY, SUNDAY -> "Hooray, time to rest!";
default -> "Workday.";
};
System.out.println(mood);
Example with String
String season = "summer";
String activity = switch (season)
{
case "winter" -> "Go ice skating";
case "summer" -> "Swim in the lake";
case "autumn" -> "Pick mushrooms";
case "spring" -> "Listen to birds singing";
default -> "Unknown season";
};
System.out.println(activity);
6. Rewriting the old switch in the new style
Before:
int day = 3;
String dayName;
switch (day)
{
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
default:
dayName = "Unknown day";
break;
}
System.out.println(dayName);
After:
int day = 3;
String dayName = switch (day)
{
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
default -> "Unknown day";
};
System.out.println(dayName);
Another example: multiple case labels — same logic
int score = 5;
String grade = switch (score)
{
case 5, 6, 7 -> "Good";
case 8, 9, 10 -> "Excellent";
default -> "Needs improvement";
};
System.out.println(grade);
7. Common mistakes and nuances
Error #1: missing default when not all cases are handled. If you use a switch expression with a type that can have values outside the listed case labels (for example, with int or String), the compiler will require a default. For an enum, if you don’t handle all values, default is required too.
Error #2: forgot yield in the block. If you use braces for a case (you need to perform several actions), don’t forget yield — without it the compiler will report an error: "Missing yield statement".
Error #3: type mismatch. All branches of a switch expression must return values of the same type; otherwise the compiler won’t accept the code.
Error #4: duplicate case labels. You can’t specify the same case twice — the compiler will immediately report an error.
GO TO FULL VERSION