Java Switch Expressions: Arrow Labels and yield
Introduction
The classic switch statement has two well-known problems - forgetting a
(Note - This tutorial builds on the classic switch statementClick to read tutorial: Java switch Statement Tutorial with Examples.) Arrow labels - no more fall-through Instead of
OUTPUT of the above code
Compare the first switch with the fall-through bug in the switch statement tutorialClick to read tutorial: Java switch Statement Tutorial with Examples: here only
OUTPUT of the above code
Explanation of the code
yield - returning a value from a block
When a case needs several statements before it can produce its value, use a block, and give the value with
OUTPUT of the above code
Note -
OUTPUT on compiling the above code
This is a big advantage over the classic switch statement. If someone later adds a constant to an enum, every switch expression which does not handle it fails to compile, instead of silently doing nothing at runtime. Leave out
Handling null and type patterns (Java 21)
Java 21 made switch even more powerful -
OUTPUT of the above code
Explanation of the code
break causes fall-through, and getting a value out of a switch needs a variable assigned in every case. Switch expressions, standard since Java 14, fix both. This tutorial explains Java switch expressions with arrow labels and yield. We will start with arrow labels, which never fall through. We will then use switch as an expression which produces a value, and use yield to return a value from a block. Next we will see how the compiler checks that a switch expression covers every possible value. Lastly, we will take a first look at handling null and at pattern matching in switch, added in Java 21.(Note - This tutorial builds on the classic switch statementClick to read tutorial: Java switch Statement Tutorial with Examples.) Arrow labels - no more fall-through Instead of
case value:, write case value ->. With an arrow label, only the code to the right of the arrow runs - there is no fall-through, and no break is needed. The right-hand side can be a single expression, a block in braces, or a throw statement. Several values can share one label, separated by commas.
A switch statement with arrow labels
//ArrowSwitch.java
public class ArrowSwitch {
public static void main(String[] args) {
int level = 2;
switch (level) {
case 1 -> System.out.println("Level 1: Beginner");
case 2 -> System.out.println("Level 2: Intermediate");
case 3 -> System.out.println("Level 3: Advanced");
default -> System.out.println("Unknown level");
}
String day = "SUN";
switch (day) {
case "SAT", "SUN" -> System.out.println(day + ": weekend - lie in!");
case "MON", "TUE", "WED", "THU", "FRI" -> {
System.out.println(day + ": weekday");
System.out.println("Alarm set for 7:00");
}
default -> System.out.println("Not a day: " + day);
}
}
}
Level 2: Intermediate SUN: weekend - lie in!
case 2 ran. A single switch must use either arrow labels or colon labels throughout - they cannot be mixed.
Switch as an expression
A switch can also be an expression which produces a value. The value of the matching case becomes the value of the whole switch, which can be assigned to a variable, returned, or passed to a method. Note the semicolon after the closing brace when it is part of a statement.
A switch expression that returns a value
//SwitchExpression.java
public class SwitchExpression {
static int daysIn(int month, boolean leapYear) {
return switch (month) {
case 4, 6, 9, 11 -> 30;
case 2 -> leapYear ? 29 : 28;
case 1, 3, 5, 7, 8, 10, 12 -> 31;
default -> throw new IllegalArgumentException("Invalid month: " + month);
};
}
public static void main(String[] args) {
String size = "M";
double price = switch (size) {
case "S" -> 9.99;
case "M" -> 12.99;
case "L", "XL" -> 14.99;
default -> 0;
};
System.out.println("Price of size " + size + ": " + price);
System.out.println("Days in February 2028: " + daysIn(2, true));
System.out.println("Days in month 13: " + daysIn(13, false));
}
}
Price of size M: 12.99 Days in February 2028: 29 Exception in thread "main" java.lang.IllegalArgumentException: Invalid month: 13 at SwitchExpression.daysIn(SwitchExpression.java:8) at SwitchExpression.main(SwitchExpression.java:22)
- Compare
daysIn()with the same method in the switch statement tutorial - nodaysvariable, nobreaks, and the whole method is a singlereturn. - A
throwis allowed on the right of an arrow, which is a clean way to reject invalid values. Here it throws anIllegalArgumentExceptionfor month 13. - The
default -> 0case returns anint, which is promoted todoublealong with the other values.
yield. yield is to a switch expression what return is to a method - it ends the case and supplies the switch's value.
Using yield in a switch expression
//YieldDemo.java
public class YieldDemo {
static double shippingCost(String zone, double weightKg) {
return switch (zone) {
case "LOCAL" -> 2.50;
case "NATIONAL" -> {
double cost = 4.00 + weightKg * 0.50;
yield Math.min(cost, 15.00); // capped at 15
}
case "INTERNATIONAL" -> {
if (weightKg > 20) {
yield -1; // too heavy to ship
}
yield 12.00 + weightKg * 2.00;
}
default -> throw new IllegalArgumentException("Unknown zone: " + zone);
};
}
public static void main(String[] args) {
System.out.println("LOCAL, 3 kg : " + shippingCost("LOCAL", 3));
System.out.println("NATIONAL, 3 kg : " + shippingCost("NATIONAL", 3));
System.out.println("NATIONAL, 40 kg : " + shippingCost("NATIONAL", 40));
System.out.println("INTERNATIONAL, 3 kg : " + shippingCost("INTERNATIONAL", 3));
System.out.println("INTERNATIONAL, 25 kg : " + shippingCost("INTERNATIONAL", 25));
}
}
LOCAL, 3 kg : 2.5 NATIONAL, 3 kg : 5.5 NATIONAL, 40 kg : 15.0 INTERNATIONAL, 3 kg : 18.0 INTERNATIONAL, 25 kg : -1.0
yield also works in switch expressions which use the old colon labels - case 1: yield "one"; - but arrow labels are clearer and are preferred.
Exhaustiveness - covering every value
A switch expression must always produce a value, so the compiler checks that it is exhaustive - that every possible input is handled. For an int or String, that means a default is required. For an enum, listing every constant is enough, and no default is needed. If a constant is missing, the code does not compile -
A switch expression that misses an enum constant
//Seasons.java
public class Seasons {
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
static String describe(Season season) {
return switch (season) {
case WINTER -> "cold";
case SPRING -> "mild";
case SUMMER -> "hot";
};
}
}
Seasons.java:6: error: the switch expression does not cover all possible input values
return switch (season) {
^
1 error
default when switching on an enum, so that you get this check.
- case null: A switch normally throws a
NullPointerExceptionwhen the value isnull. Adding acase nullhandles it instead. - Type patterns: A case can test the type of an object and give it a name in one step -
case Integer i ->matches anyInteger, and makes it available asi. - Guards:
whenadds an extra condition to a pattern -case Integer i when i < 0 ->.
case null and type patterns in a switch (Java 21+)
//PatternSwitch.java
public class PatternSwitch {
static String describe(Object value) {
return switch (value) {
case null -> "nothing at all";
case Integer i when i < 0 -> "a negative number: " + i;
case Integer i -> "a number: " + i;
case String s when s.isBlank() -> "a blank string";
case String s -> "a string of length " + s.length();
default -> "something else: " + value.getClass().getSimpleName();
};
}
public static void main(String[] args) {
System.out.println(describe(42));
System.out.println(describe(-7));
System.out.println(describe("Java"));
System.out.println(describe(" "));
System.out.println(describe(3.14));
System.out.println(describe(null));
}
}
a number: 42 a negative number: -7 a string of length 4 a blank string something else: Double nothing at all
- Cases are checked from top to bottom, so the guarded case
Integer i when i < 0must come before the plainInteger icase. The compiler reports an error if a case can never be reached. - Inside each case,
iandsalready have the right type - no cast is needed. - Pattern matching becomes really useful with classes, records and sealed types, which are covered later in this series. For now, remember that switch can do much more than compare constants.
throw for invalid input. Next we used yield to produce a value from a block of statements. We then saw that switch expressions must be exhaustive, and that the compiler checks enum switches for missing constants. Lastly, we handled null and matched on types with patterns and guards, available since Java 21. In the next tutorial, we move on to loops, starting with the for loopClick to read tutorial: Java for Loop Tutorial with Examples.Java Fundamentals Tutorials
Java switch Statement Tutorial with ExamplesClick to read tutorial: Java switch Statement Tutorial with Examples Java for Loop Tutorial with ExamplesClick to read tutorial: Java for Loop Tutorial with Examples Java if, else if and else Statements with ExamplesClick to read tutorial: Java if, else if and else Statements with Examples Java while and do-while Loops with ExamplesClick to read tutorial: Java while and do-while Loops with Examples Java Enhanced for Loop (for-each) with ExamplesClick to read tutorial: Java Enhanced for Loop (for-each) with Examples Java break, continue and Labeled Loops ExplainedClick to read tutorial: Java break, continue and Labeled Loops Explained What is Java? History, Features, Editions and UsesClick to read tutorial: What is Java? History, Features, Editions and Uses
Java switch Statement Tutorial with ExamplesClick to read tutorial: Java switch Statement Tutorial with Examples Java for Loop Tutorial with ExamplesClick to read tutorial: Java for Loop Tutorial with Examples Java if, else if and else Statements with ExamplesClick to read tutorial: Java if, else if and else Statements with Examples Java while and do-while Loops with ExamplesClick to read tutorial: Java while and do-while Loops with Examples Java Enhanced for Loop (for-each) with ExamplesClick to read tutorial: Java Enhanced for Loop (for-each) with Examples Java break, continue and Labeled Loops ExplainedClick to read tutorial: Java break, continue and Labeled Loops Explained What is Java? History, Features, Editions and UsesClick to read tutorial: What is Java? History, Features, Editions and Uses