Java 17 具有模式匹配的 null 情况

Gar*_*son 8 java eclipse pattern-matching switch-statement java-17

我有一个使用 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)
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用新的 Java 17 开关功能,因此我在方法中尝试了以下方法:

return switch(testEnum) {
  case foo -> newFoo();
  case bar -> newBar();
}
Run Code Online (Sandbox Code Playgroud)

效果很好。但后来我尝试了这个(因为该值可能是null):

return switch(testEnum) {
  case foo -> newFoo();
  case bar -> newBar();
  case null -> newDefault();
}
Run Code Online (Sandbox Code Playgroud)

Eclipsenull用红色下划线表示:

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)
Run Code Online (Sandbox Code Playgroud)

我的 Maven 项目有:

<properties>
  <maven.compiler.release>17</maven.compiler.release>
</properties>
Run Code Online (Sandbox Code Playgroud)

我知道编译器版本设置不会被忽略;否则它将默认为 Java 8(根据我的父 POM)并且根本不允许模式匹配。

模式匹配的 null 情况不是 Java 17 的一部分吗?我究竟做错了什么?

Bas*_*que 19

更新:模式匹配已switch 到达 Java 21

\n

太长了;博士

\n

switch表达式 != 模式匹配switch

\n

switch您将表达式的相对较新的功能与尚未发布的模式匹配switch功能混合在一起。

\n

Java 中的功能switch已经发展了 3 个阶段,其中两个阶段已完成:

\n
    \n
  • \xe2\x98\x91\xef\xb8\x8fswitch语句(Java 1 中的原始功能)
  • \n
  • \xe2\x98\x91\xef\xb8\x8fswitch表达式 (Java 14+)
  • \n
  • \xe2\x9d\x8c 的模式匹配switch,包括case null(在 Java 17、18、19 和 20 中预览)
  • \n
\n

不要将switch表达式与模式匹配混为一谈

\n

经典的switch

\n

要了解,从历史上看,Javaswitch语句一直敌视null检查。请参阅这个问题,如何在 switch 中使用 null。如图所示,代码如下:

\n
switch (i) {\n    case null:\n        doSomething0();\n        break;    \n}\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\xa6 是不可能的。

\n

switch表达式

\n

快进到 Java 14,switchJava 中添加了表达式。请参阅JEP 361:切换表达式。这允许使用第一个代码示例中看到的语法:

\n
return switch(testEnum) {\n  case foo -> newFoo();\n  case bar -> newBar();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但请阅读 JEP。没有提及null\xe2\x80\x94 \xc2\xab 蟋蟀 \xc2\xbb。

\n

模式匹配为switch

\n

进一步快进到JEP 406:交换机的模式匹配(预览)。请注意,这是 Java 17 中的预览功能,而不是最终的正式发布功能。(要了解预览功能的工作原理,请阅读JEP 12:预览功能。)

\n

在该 JEP 406 中,请注意其第二个目标:允许在需要时放松切换的历史零敌意

\n

现在搜索该页面 \xe2\x80\x9cnull\xe2\x80\x9d \xe2\x80\x94\xc2\xa073 命中!该页面解释了 Java 语言以前的政策:

\n
\n

传统上,如果选择器表达式的计算结果为\xe2\x80\xa6,则switch语句和表达式会抛出异常NullPointerExceptionnull

\n
\n

请注意语句(原始语法)的提及switch,以及代码中使用的新语法(表达式) 。在这两种情况下,null检查都被禁止。

\n

该页面继续解释了促使包含空检查支持的更改。请阅读 JEP 以了解遗嘱的详细信息。

\n

结果是,您可以case nullswitchJava 17 \xe2\x80\x94 中使用,但前提是您不遗余力地启用预览功能

\n

仍处于预览阶段,在 Java 20 中

\n\n

“我们不会在时机到来之前出售任何葡萄酒。”

\n

在 Java 20 中,您也必须不遗余力地激活预览功能

\n

当然还有两点提醒:

\n
    \n
  • 预览功能不应在关键应用程序的生产中使用。
  • \n
  • 预览功能可能会发生变化。这就是他们的目的,收集导致变革的反馈和建议。
  • \n
\n

例子

\n

让我们尝试一下这个代码示例。请注意我们在这里如何使用普通的旧语法,没有->. 箭头运算符与我们这里的讨论无关。

\n
String x = null;\nswitch ( x )\n{\n    case "starburst":\n        System.out.println( "Is starburst." );\n        break;\n    case null:\n        System.out.println( "Whoops, null." );\n        break;\n    default:\n        System.out.println( "Some other value found." );\n        break;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在 Java 17 中,默认情况下,如果不启用预览功能,我们在编辑以下代码时会收到此错误case null

\n
\n

语言级别“17”不支持 switch 中的模式

\n

将语言级别设置为 17(预览) - 开关的模式匹配

\n
\n

在 Java 17 中启用预览功能后,代码可以顺利编译。它运行:

\n
\n

哎呀,空。

\n
\n


tgd*_*ies 1

这个命令行对我有用:

$ 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
Run Code Online (Sandbox Code Playgroud)