我有一个使用 Eclipse 2022-03 和 OpenJDK 17 的 Java 17 项目:
openjdk 17.0.2 2022-01-18
OpenJDK Runtime Environment Temurin-17.0.2+8 (build 17.0.2+8)
OpenJDK 64-Bit Server VM Temurin-17.0.2+8 (build 17.0.2+8, mixed mode, sharing)
我正在尝试使用新的Java 17开关功能,所以我在一个方法中尝试了这个:
return switch(testEnum) {
case foo -> newFoo();
case bar -> newBar();
}
效果很好。但后来我尝试了这个(因为该值可能是
null
):
return switch(testEnum) {
case foo -> newFoo();
case bar -> newBar();
case null -> newDefault();
}
Eclipse 用红色下划线
null
并表示:
Switch 中的模式匹配是预览功能,默认情况下处于禁用状态。使用 --enable-preview 启用
通过 Maven 编译会产生:
[ERROR] /project/src/main/java/com/example/FooBar.java:[432,38] null in switch cases is a preview feature and is disabled by default.
[ERROR] (use --enable-preview to enable null in switch cases)
我的 Maven 项目有:
<properties>
<maven.compiler.release>17</maven.compiler.release>
</properties>
我知道编译器版本设置不会被忽略;否则它将默认为 Java 8(根据我的父 POM)并且根本不允许模式匹配。
模式匹配的 null 情况不是 Java 17 的一部分吗?我做错了什么?
更新:
switch
的模式匹配已在 Java 21 中实现。
👉
switch
表达式 != 与 switch
的模式匹配
您将
switch
表达式的相对较新的功能与尚未发布的模式匹配功能与switch
混淆了。
Java 中的
switch
功能已经发展了 3 个阶段,其中两个阶段已完成:
switch
语句(Java 1 中的原始功能)switch
表达式 (Java 14+)switch
的模式匹配,包括 case null
(在 Java 17、18、19 和 20 中预览)switch
表达式与模式匹配混为一谈switch
了解,从历史上看,Java
switch
声明一直对null
检查怀有敌意。请参阅这个问题,如何在 switch 中使用 null。如图所示,代码如下:
switch (i) {
case null:
doSomething0();
break;
}
...不可能。
switch
表情快进到 Java 14,当时
switch
表达式被添加到 Java 中。请参阅JEP 361:切换表达式。这允许您在第一个代码示例中看到的语法:
return switch(testEnum) {
case foo -> newFoo();
case bar -> newBar();
}
但是请阅读 JEP。没有提到
null
——“蟋蟀”。
switch
进一步快进,到JEP 406:开关模式匹配(预览)。请注意,这是 Java 17 中的预览功能,而不是最终的正式发布功能。 (要了解预览功能的工作原理,请阅读 JEP 12:预览功能。)
👉 在 JEP 406 中,请注意它的第二个目标:允许在需要时放松 switch 的历史零敌意。
现在在该页面搜索“null”——73 次点击!该页面解释了 Java 语言以前的政策:
传统上,如果选择器表达式的计算结果为
…switch
,则NullPointerException
语句和表达式会抛出null
请注意提到了 statements(原始
switch
语法),以及另外的 expressions(代码中使用的新语法)。在这两种情况下,null
检查都被禁止。
该页面继续解释了促使包含空检查支持的更改。阅读 JEP 了解遗嘱详细信息。
👉 结果是,您可以在 Java 17 的
case null
中使用 switch
— 但前提是您不遗余力地启用预览功能。
在 Java 20 中,您也必须不遗余力地激活预览功能。
当然还有两点提醒:
让我们尝试一下这个代码示例。请注意我们在这里如何使用普通的旧语法,没有
->
。箭头运算符与我们这里的讨论无关。
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;
}
在 Java 17 中,默认情况下,如果不启用预览功能,我们在编辑
case null
的代码时会收到此错误:
语言级别“17”不支持 switch 中的模式
将语言级别设置为 17(预览)- 开关的模式匹配
在 Java 17 中启用预览功能后,代码编译没有任何问题。它运行:
哎呀,空。
这个命令行对我有用:
$ javac -version
javac 17.0.3
$ javac -source 17 -Xlint:preview --enable-preview org/kablambda/Main.java
org/kablambda/Main.java:10: warning: [preview] null in switch cases is a preview feature and may be removed in a future release.
case null -> "c";
^
1 warning
return (null == testEnum)
? newDefault()
: switch (testEnum) {
case foo -> newFoo();
case bar -> newBar();
};