Java switch expression

Java Switch Expression

Author image
by Sven WoltmannFebruary 2, 2022

Article Series: Project Amber

In Project Amber, new Java language features are being developed and gradually released.

Part 1: Switch Expressions (Java 14)

Part 2: Text Blocks (Java 15)

Part 3: Records (Java 16)

Part 4: Sealed Classes (Java 17)

(Sign up for the HappyCoders Newsletter
to be immediately informed about new parts.)

Switch Expressions were released in Java 14 under Project Amber.

Switch Expressions are actually two enhancements that can be used independently but also combined:

  1. Arrow notation without break and fall-throughs
  2. Using switch as an expression with a return value

Let's look at the changes one by one (I'm using the examples from JEP 361, slightly modified).

Starting Point

In the following example, we print the word length for a given day of the week. For the last two cases, I wrote the code a bit more complicated than necessary to demonstrate what is possible with switch expressions.

switch (day) { case MONDAY: case FRIDAY: case SUNDAY: System.out.println(6); break; case TUESDAY: System.out.println(7); break; case THURSDAY: case SATURDAY: System.out.println((int) Math.pow(2, 3)); break; case WEDNESDAY: int three = 1 + 2; System.out.println(three * three); break; }
Code language: Java (java)

This notation is confusing and error-prone due to the so-called "fall-throughs", i.e., the continuation of execution on the following case if the previous one was not terminated with a break statement.

Accordingly, such constructs are marked as code smells by static code analysis (SCA) tools such as Sonar, Checkstyle, and PMD:

Static code analysis (SCA) warnings for 'switch' statements without 'break'
Static code analysis (SCA) warnings for 'switch' statements without 'break'

Switch with Arrow Notation

The following example shows using an arrow instead of a colon, starting with Java 14. The following rules apply:

  • Before the arrow, you may list several cases separated by commas.
  • The arrow may be followed by either a single code statement (lines 2, 3, and 4) or a code block in curly braces (lines 5 to 8).
  • break statements are omitted in this notation.

Here is a sample code for a switch statement in arrow notation:

switch (day) { case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); case TUESDAY -> System.out.println(7); case THURSDAY, SATURDAY -> System.out.println((int) Math.pow(2, 3)); case WEDNESDAY -> { int three = 1 + 2; System.out.println(three * three); } }
Code language: Java (java)

Modern IDEs like IntelliJ recognize the improvement potential and offer an automatic conversion to the new format:

Automatic replacement of 'switch' statements
Automatic replacement of 'switch' statements

Switch as an Expression with a Return Value

We often use switch to assign a case-specific value to a variable. In the following example, instead of printing the weekday's length, we store it in the numLetters variable:

(The last two cases are again intentionally written verbosely to show what is possible with switch expressions.)

int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = (int) Math.pow(2, 3); break; case WEDNESDAY: int three = 1 + 2; numLetters = three * three; break; default: throw new IllegalStateException("Unknown day: " + day); }
Code language: Java (java)

To use the variable afterward, we must – even though we have covered every weekday – either initialize the variable beforehand or specify a default case. Otherwise, the compiler would abort with the error message "Variable 'numLetters' might not have been initialized".

As of Java 14, we can convert this statement into an expression. To do so, we return each value using the new keyword yield. We then assign the result of the switch expression directly to the variable:

int numLetters = switch (day) { case MONDAY: case FRIDAY: case SUNDAY: yield 6; case TUESDAY: yield 7; case THURSDAY: case SATURDAY: yield (int) Math.pow(2, 3); case WEDNESDAY: int three = 1 + 2; yield three * three; default: throw new IllegalStateException("Unknown day: " + day); };
Code language: Java (java)

yield is a so-called "contextual keyword"; it therefore only has meaning in the context of a switch expression. Should you have used yield as a variable name in your source code – don't worry; you can still do that. Even something like that would be allowed:

int yield = 5; yield yield + yield;

Arrow Notation and Switch Expression Combined

The switch expression just shown becomes much more elegant if we write it in arrow notation. We can write the return value

  • directly behind the arrow (lines 2 and 3),
  • as an expression or method call behind the arrow (line 4),
  • or return it with yield from a code block (line 7).
int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> (int) Math.pow(2, 3); case WEDNESDAY -> { int three = 1 + 2; yield three * three; } default -> throw new IllegalStateException("Unknown day: " + day); };
Code language: Java (java)

We can also let our IDE do the complete refactoring from the conventional switch statement to the switch expression with arrow notation:

Automatic replacement of 'switch' statements by 'switch' expressions
Automatic replacement of 'switch' statements by 'switch' expressions

Completeness Analysis for Enums

As the variable day is an enum, the compiler can recognize that we have covered all cases. Thus, we may omit the default case:

int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> (int) Math.pow(2, 3); case WEDNESDAY -> { int three = 1 + 2; yield three * three; } };
Code language: Java (java)

Our IDE is happy to do that for us as well:

Automatic removal of the 'default' branch
Automatic removal of the 'default' branch

The notation without default case is shorter and assists us in future extensions of the enum. If we extend it – e.g., by a NEWDAY – the compiler will tell us that the switch expression is now incomplete:

Incomplete 'switch' expression
Incomplete 'switch' expression

So switch expressions can also make our code more robust.

Summary

Switch expressions are a powerful tool. The arrow notation and the use as an expression with a return value allow a much more concise and less error-prone notation than before.

Switch expressions were first introduced in Java 12 as a preview feature. In the second preview in Java 13, the break keyword, initially used to return values, was replaced by yield. With JDK Enhancement Proposal 361, Switch Expressions were released as a final feature in Java 14 without any further changes.

If you liked the article, feel free to share it using one of the share buttons and leave me a comment: Have you already had the opportunity to use the new Switch Expressions? If yes, how do you like them? If not, why not?

Do you want to be informed when new articles are published on HappyCoders.eu? Then click here to sign up for HappyCoders.eu newsletter.