Java 17 has come up with some cool features for the language, one of which is switch expressions. Maybe someone wonders, – But, does the switch already exists in Java? and the answer is yes, as a statement that only evaluates a data but does not return a value. That is the difference, being an expression it can return values, also include patterns to the case.
It is important to note that switch expressions have been in the language since previous versions of Java, starting in Java 12 in preview mode and receiving constant improvements with the following versions of Java. It is up to Java 17 that it is available in a stable long support (LTS) release.
This is the first step towards a more declarative and “null-safe” programming style, allowing a better way to express and model data, recognizing the semantics of the data model through patterns. Definitively improving the readability of our code, avoiding nested if/elseif/else
for many circumstances, and providing features that we see in other programming languages.
Let’s take the following code as reference, with some if/else if
and instanceof
.
static String formatter(Object o) { String formatted = "unknown"; if (o instanceof Integer i) { formatted = String.format("int %d", i); } else if (o instanceof Long l) { formatted = String.format("long %d", l); } else if (o instanceof Double d) { formatted = String.format("double %f", d); } else if (o instanceof String s) { formatted = String.format("String %s", s); } return formatted; }
The previous code can be converted with a switch expression.
static String formatterPatternSwitch(Object o) { return switch (o) { case Integer i -> String.format("int %d", i); case Long l -> String.format("long %d", l); case Double d -> String.format("double %f", d); case String s -> String.format("String %s", s); default -> o.toString(); }; }
Switch Expression vs Switch Statement
Now, how are the switch expression and statement going to co-exist? The first difference is in the operator used after the case
, the expression uses an arrow ->
while the statement continues using the operator :
(colon).
//Switch Expression example switch (o) { case Integer i -> String.format("int %d", i); case Long l -> String.format("long %d", l); } //Switch Statement example switch (o) { case Integer i: String.format("int %d", i); break; case Long l: String.format("long %d", l); break; }
It can be noticed that in the switch statement is still necessary to use the break
statement to terminate the switch flow, in other words, if break
is not indicated, it will continue executing the code blocks of the following labels. On the other hand, in the switch expression, only the code block of the matching pattern or value is executed.
It should be noted that both the sentence and the expression continue to work with exact or constant values, not only with patterns that it matches. For example, the following code is still valid.
//Switch statement switch (value) { case "A": callMethod1(); break; case "B": callMethod2(); break; default: callMethod3(); } //Switch Expression switch (value) { case "A"-> callMethod1(); case "B"-> callMethod2(); default -> callMethod3(); }
Support of null
Traditionally, the switch throws a NullPointerException
when the value is null
. This behavior is still present for existing switch statements, which do not make use of patterns. However, to make the new features of the switch more user-friendly (both the statement and the expression) allow null
as part of the pattern.
switch (o) { case null -> System.out.println("null!"); case String s -> System.out.println("String"); default -> System.out.println("Something else"); }
Guarded Pattern
This is a feature that I have seen in other languages and I think it was very successful that it is being added in Java as well. The “guarded pattern” is a condition that is part of an expression that must be matched and is preceded by the &&
operator.
switch(value) { case String s && (s.length > 3) -> System.out.println("A short string"); case String s && (s.length > 10 -> System.out.println("A medium string"); default -> System.out.println("A long string"); }
Conclusión
There are many other features of the switch that are not listed in this article, however, it is about showing the main ones, which I believe can provide a great improvement in usability to our code.
Definitely, Java as a language continues to evolve and provide features that will further simplify our code and keep it on par with many other new languages that are trending at the moment.
References
- https://openjdk.java.net/jeps/406
- https://www.infoworld.com/article/3606833/jdk-17-the-new-features-in-java-17.html
Hi and thank you so much for the above article. I am typing your code into IDE, and I get a compiler error saying “Patterns in switch are not support at language level 19”
public static String formattedWithSwith(Object o){
return switch (o){
case Integer i-> String.format(“int i”,i);
default -> o.toString();
};
}
I get the red squiggly right under the “i”
I think it should be an issue of the IDE, for example it has been reported for IntelliJ on other versions of Java.
https://youtrack.jetbrains.com/issue/IDEA-295898
But the code compiles correctly. Can you verify that compiling your code the issue is not happening?
If so, then it’s just the IDE which doesn’t have support for that new feature in Java. Hopefully new versions of the IDE will fix it.
P.S. I am using OpenJDK