Java 17 null case 与模式匹配

问题描述 投票:0回答:3

我有一个使用 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 的一部分吗?我做错了什么?

java eclipse switch-statement pattern-matching java-17
3个回答
20
投票

更新:

switch
的模式匹配已在 Java 21 中实现

tl;博士

👉

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 仍处于预览阶段

“我们不会在此之前出售任何葡萄酒。”

在 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 中启用预览功能后,代码编译没有任何问题。它运行:

哎呀,空。


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

0
投票
return (null == testEnum)
    ? newDefault()
    : switch (testEnum) {
      case foo -> newFoo();
      case bar -> newBar();
    };
© www.soinside.com 2019 - 2024. All rights reserved.