Update: Pattern matching for switch
arrived in Java 21.
tl;dr
👉 switch
expressions != pattern matching with switch
You are mixing up the relatively new feature of switch
expressions with the still-not-released feature of pattern matching with switch
.
The switch
feature in Java has been evolving through 3 phases, two completed:
- ☑️
switch
statement (original feature in Java 1)
- ☑️
switch
expression (Java 14+)
- ❌ Pattern matching for
switch
, including case null
(previewed in Java 17, 18, 19, & 20)
Do not conflate switch
expressions with pattern matching
Classic switch
Understand that historically, the Java switch
statement has been hostile to null
checks. See this Question, How to use null in switch. As shown there, code such as this:
switch (i) {
case null:
doSomething0();
break;
}
… was not possible.
switch
expressions
Fast forward to Java 14, when switch
expressions was added to Java. See JEP 361: Switch Expressions. That allows the syntax seen in your first code example:
return switch(testEnum) {
case foo -> newFoo();
case bar -> newBar();
}
But read the JEP. No mention of null
— « crickets ».
Pattern matching for switch
Fast forward further, to JEP 406: Pattern Matching for switch (Preview). Note that this is a preview feature in Java 17, not a final, officially released feature. (To understand how preview features work, read JEP 12: Preview Features.)
👉 In that JEP 406, notice its second goal: Allow the historical null-hostility of switch to be relaxed when desired.
Now search that page for “null” — 73 hits! That page explains the former policy of the Java language:
Traditionally, switch
statements and expressions throw NullPointerException
if the selector expression evaluates to null
…
Notice the mention of statements, the original switch
syntax, and additionally expressions, the new syntax used in your code. In both cases, null
check was forbidden.
That page goes on to explain the changes that motivate the inclusion of support for null checks. Read the JEP for will-written details.
👉 The upshot is that you can use case null
in a switch
in Java 17 — but only if you go out of your way to enable the preview feature.
Still in preview, in Java 20
"We will sell no wine before its time."
There too, in Java 20, you will have to go out of your way to activate the preview feature.
And of course two reminders:
- Preview features should not be used in production for critical apps.
- Preview features are likely to change. That is their purpose, to gather feedback and suggestions leading to changes.
Example
Let's try this code example. Notice how we use plain old syntax here, without the ->
. The arrow operator is not related to our discussion here.
String x = null;
switch ( x )
{
case "starburst":
System.out.println( "Is starburst." );
break;
case null:
System.out.println( "Whoops, null." );
break;
default:
System.out.println( "Some other value found." );
break;
}
In Java 17, by default, without enabling preview features we get this error while editing the code for case null
:
Patterns in switch are not supported at language level '17'
Set language level to 17 (Preview) - Pattern matching for switch
After enabling preview features in Java 17, the code compiles without complaint. And it runs:
Whoops, null.
javac
say when you compile that file? – Nimwegenjavac
), and it gave the same error! I updated the question with this additional information. – Crowdernull
cases was present in Java 17, but I guess that is different than pattern matching. So pattern matching is a full feature in Java 17, andnull
case statements is a full feature in Java 17, but pattern matching withnull
is only a preview feature in Java 17? That's sort of confusing. – CrowderNullPointerException
at runtime. Seems, that support isn’t complete. – Unbated