The switch Expression Flashcards
switch expression
- switch expressions that were officially added to Java 14.
- A switch expression is a much more compact form of a switch statement, capable of returning a value.
int result = switch(variableToTest) { case constantExpression1 -> 5; case constantExpression2, constantExpression3 -> { yield 10; } ... default -> 0; };
- we can now assign the result of a switch expression to a variable result.
- For this to work, all case and default branches must return a data type that is compatible with the assignment.
- The switch expression supports two types of branches: an expression and a block ({}).
- Like a traditional switch statement, a switch expression supports zero or many
case
branches and an optionaldefault
branch. - Both also support the new feature that allows case values to be combined with a single case statement using
commas
. - Unlike a traditional switch statement, though, switch expressions have special rules around when the
default
branch is required. - we don’t have to worry about
break
statements, since only one branch is executed.
> [!Note]
Recall from Chapter 2, “Operators,” that ->
is the arrow
operator. While the arrow operator is commonly used in lambda expressions, when it is used in a switch expression, the case
branches are not lambdas
.
public void printDayOfWeek(int day) { var result = switch(day) { case 0 -> "Sunday"; case 1 -> "Monday"; ... default -> "Invalid"; }; System.out.print(result); }
public void printSeason(int month) { switch(month) { case 1, 2, 3 -> System.out.print("Winter"); case 4, 5, 6 -> System.out.print("Spring"); case 7, 8, 9 -> System.out.print("Summer"); case 10, 11, 12 -> System.out.print("Fall"); } }
Case statements can take multiple
values, separated by commas
.
> [!Note]
Most of the time, a switch expression returns a value, although printSeason() demonstrates one in which the return type is void. Since the type is void, it can’t be assigned to a variable. On the exam, you are more likely to see a switch expression that returns a value, but you should be aware that it is possible.
> [!Note]
Most of the time, a switch expression returns a value, although printSeason() demonstrates one in which the return type is void. Since the type is void, it can’t be assigned to a variable. On the exam, you are more likely to see a switch expression that returns a value, but you should be aware that it is possible.
- All of the branches of a switch expression that do not throw an exception must return a consistent data type (if the switch expression returns a value).
- If the switch expression returns a value, then every branch that isn’t an expression must yield a value.
- A default branch is required unless all cases are covered or no value is returned.
Returning Consistent Data Types
The first rule of using a switch expression is probably the easiest. You can’t return incompatible or random data types.
int measurement = 10; int size = switch(measurement) { case 5 -> 1; case 10 -> (short)2; default -> 5; case 20 -> "3"; // DOES NOT COMPILE case 40 -> 4L; // DOES NOT COMPILE case 50 -> null; // DOES NOT COMPILE };
the second case expression returns a short, but that can be implicitly cast to an int.
The last three case expressions do not compile because each returns a type that cannot be assigned to the int variable.
Applying a case Block
A switch expression supports both an expression
and a block
in the case and default branches. Like a regular block, a case block is one that is surrounded by braces ({}). It also includes a yield statement if the switch expression returns a value.
int fish = 5; int length = 12; var name = switch(fish) { case 1 -> "Goldfish"; case 2 -> {yield "Trout";} case 3 -> { if (length > 10) yield "Blobfish"; else yield "Green"; } default -> "Swordfish"; };
Applying a case Block
> [!NOTE]
Watch Semicolons in switch Expressions
Unlike a regular switch statement, a switch expression can be used with the assignment operator and requires a semicolon when doing so. Furthermore, semicolons are required for case expressions but cannot be used with case blocks.
var name = switch(fish) { case 1 -> "Goldfish" // DOES NOT COMPILE (missing semicolon) case 2 -> {yield "Trout";}; // DOES NOT COMPILE (extra semicolon) ... } // DOES NOT COMPILE (missing semicolon)
> A bit confusing, right? It’s just one of those things you have to train yourself to spot on the exam.
Covering All Possible Values
The last rule about switch expressions is probably the one the exam is most likely to try to trick you on a switch expression that returns a value must handle all possible input values.
String type = switch(canis) { // DOES NOT COMPILE case 1 -> "dog"; case 2 -> "wolf"; case 3 -> "coyote"; };
Every switch expression must handle all possible values of the switch variable. As a developer, there are two ways to address this:
- Add a
default
branch. - If the switch expression takes an
enum
value, add a case branch for every possible enum value.
For enums, the second solution works well when the number of enum values is relatively small. For example, consider the following enum definition and method:
enum Season {WINTER, SPRING, SUMMER, FALL} String getWeather(Season value) { return switch(value) { case WINTER -> "Cold"; case SPRING -> "Rainy"; case SUMMER -> "Hot"; case FALL -> "Warm"; }; }
Since all possible permutations of Season are covered, a default branch is not required in this switch expression. You can include an optional default branch, though, even if you cover all known values.
> [!Tips]
What happens if you use an enum with three values and later someone adds a fourth value? Any switch expressions that use the enum without a default branch will suddenly fail to compile. If this was done frequently, you might have a lot of code to fix! For this reason, consider including a default branch in every switch expression, even those that involve enum values.