New Switch Expressions in Java 14
Java 14 is going to be released on March 17, 2020. The new version of Java contains one major update to the Java language: new switch expressions. Let’s see how the new switch expressions can be used, what kind of advantages they offer, and what can potentially go wrong. In the end, you are going to find a tricky question about the switch expressions.
(the article has been published on Medium)
The classic switch statement
The current design of the switch
statement in Java follows languages such as C and C++. It works only as a statement and supports fall through semantics by default. Here is an example of the classic switch
statement with an enum:
You might have noticed many case
and break
statements in the example above. Those statements introduce some visual noise and make the code unnecessarily verbose. This visual noise may then mask mistakes such a missing break
statement which would mean accidental fall through.
The new switch expressions
Java 14 extends switch
so that it can be used as either a statement or an expression. In particular, the new Java introduces the following:
- A new form of switch label
case ... ->
where only the code to the right of the label is going to be executed if the label is matched. The code to the right of acase ... ->
label may be an expression, a block, or a throw statement. - A new
yield
statement to yield a value which becomes the value of the enclosing switch expression. - Multiple constants per case which are separated by commas.
With the new Java 14, it’s possible to use both traditional case … :
labels and new case … ->
labels. It is important that the traditional labels still support fall through by default, but the new ones don’t.
Let’s see how the example above can be re-written with the new switch expressions:
This simple example can be compiled and run with just a single command (thanks to JEP 330 which allowed launching single-file source-code programs since Java 11):
$ java WhoIsWho.java
Mozart was a composer
Dali was a painter
Dostoevsky was a writer
You can see that several case
statements have been merged, and the code doesn’t use break
statement any more. As a result, the print()
method became much shorter and looks nicer. The following example shows a multiline default
block which uses the new yield
statement to yield a value. Note several new constants in the Person
enum which are not covered by any case
label in the switch expression:
Here is what it prints out:
$ java WhoIsWho.java
Mozart was a composer
Dali was a painter
Oops! I don't know about Einstein
Einstein was a …
The next example shows how factorial may be implemented with the new switch expressions:
Important details
There are several important things to know about the new switch expressions.
The first thing to know is that the cases of a switch expression must be exhaustive. In other words, for all possible values, there must be a matching switch label. Let’s just add a new element to the enum and see what’s going to happen:
Compilation will fail right away with the following error message:
$ java InvalidWhoIsWho.java
InvalidWhoIsWho.java:19: error: the switch expression does not cover all possible input values
String title = switch (person) {
^
1 error
error: compilation failed
Adding a simple default
case makes the Java compiler happy:
In general, unless an enum is used and the cases of a switch expression cover all constants, a default
clause is required in the switch expression.
The second thing to remember is that a switch expression must either complete normally with a value or by throwing an exception. Let’s take a look at the following code:
If we try to compile this code, the Java compiler will immediately complain:
InvalidSwitchExpressionWithoutDefault.java:8: error: the switch expression does not cover all possible input values
return switch (n) {
^
1 error
error: compilation failed
Again, adding a default
case makes it work:
The third important thing to keep in mind is that yield
is now a restricted identifier. In particular, it means that classes named “yield” become illegal:
$ cat YieldClassName.java
class yield {}
$ javac YieldClassName.java
YieldClassName.java:1: error: 'yield' not allowed here
class yield {
^
as of release 13, 'yield' is a restricted type name and cannot be used for type declarations
1 error
error: compilation failed
However, it is allowed to use “yield” as a variable or a method name:
$ cat ValidUseOfYieldWord.java
public class ValidUseOfYieldWord {
void yield() {
int yield = 0;
}
}
$ javac ValidUseOfYieldWord.java && echo ok || echo failed
ok
Conclusion
Here is what the authors say about the new switch expressions:
These changes will simplify everyday coding
Let’s see.
Bonus
What do you think is going to happen? Here are the options:
- Compilation error.
- Runtime error.
- “Oops” is printed out.
- “OopsOops” is printed out
- “Forty-two” is printed out.