我有一个使用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>
我知道编译器的发布设置没有被忽略;否则它将默认为Java8(根据我的父POM),并且根本不允许模式匹配。
模式匹配的空情况不是Java 17的一部分吗?我做错了什么?
2条答案
按热度按时间x9ybnkn61#
tl;dr
👉
switch
表达式!=与switch
匹配的模式您混淆了 *
switch
表达式 * 这一相对较新的特性和 * 模式匹配switch
* 这一尚未发布的特性。Java中的
switch
特性经历了3个阶段的发展,其中两个阶段已经完成:switch
的模式匹配,包括case null
(在Java 17、18、19和20中预览)不要将
switch
表达式与模式匹配合并经典
switch
要知道,Java
switch
语句一直以来都对null
检查持敌对态度。请参见这个问题How to use null in switch。如图所示,代码如下:......不可能。
switch
表达式快进到Java 14,此时
switch
表达式被添加到Java中。请参见JEP 361: Switch Expressions。这允许您在第一个代码示例中看到的语法:但是看看JEP,没有提到蟋蟀。
switch
的模式匹配进一步快进到JEP 406: Pattern Matching for switch (Preview)。请注意,这是Java 17中的预览特性,而不是正式发布的最终特性。(要了解预览特性如何工作,请阅读JEP 12: Preview Features。)
👉 在JEP 406中,请注意它的第二个目标:允许在需要时放松开关的历史零敌意。
现在搜索该页面中的“null”-- 73个匹配项!该页面解释了Java语言以前的策略:
传统上,如果选择器表达式的计算结果为
null
,则switch
语句和表达式将引发NullPointerException
...注意 statements(原始的
switch
语法)和 expressions(代码中使用的新语法)的提及,在这两种情况下,null
检查都被禁止。该页面继续解释了促使包含对空检查的支持的变化。阅读JEP以获得将写的细节。
👉 结果是,您可以在Java 17的
switch
中使用case null
--但前提是您必须启用预览特性。仍在预览中,Java 20
同样,在Java 20中,您将不得不特意激活预览特性。
当然还有两点提醒:
示例
让我们试试这个代码示例。注意我们在这里使用的是简单的老语法,没有
->
。箭头操作符与我们在这里讨论的内容无关。在Java 17中,默认情况下,如果不启用预览功能,我们在编辑
case null
的代码时会遇到以下错误:语言级别'17'不支持开关中模式
将语言级别设置为17(预览)-交换机的模式匹配
在Java 17中启用预览特性后,代码可以毫无问题地进行编译,并运行:
哎呦,空。
w8f9ii692#
以下命令行适用于我: