我的上一篇文章“ 玩JDK 12的Switch表达式 ”讨论了如何使用JDK 12 Early Access Builds尝试JEP 325 switch 表达式语句,并提供了一个简单的示例。 这篇文章使用相同的JDK 12 Early Access Build 10来演示switch表达式和增强的switch语句的不同功能。

我在博客文章“ 通过引入switch表达式来增强Java switch语句 ”中使用了2×2网格,以说明新的“箭头”语法(“ switch标为规则”)可以与switch 语句switch表达式一起使用。按照JEP325。类似地,按照JEP 325,传统的“冒号”语法(“带开关标记的语句组”)也可以与switch 表达式switch语句一起使用。 换句话说,结肠的存在( :并不一定意味着一个switch的“箭头”的声明 ,并存在( ->并不一定意味着一个switch 表达 。 为了方便起见,我在前面的文章中提供了表格的改编版本。

声明
(“交换机的非本地控制流_out_ [继续到封闭循环,带有标签的中断,返回]”)
表达
(总计:返回一个值)
开关标签声明组
(“结肠”)
(启用穿透)
switch我们知道和“爱”,但增强了 break返回的值类似于return
开关标签规则
(“箭头”)
(防止掉线)
语句/冒号的“语法简写”(上)以及

  • “消除了“休息”的烦恼”
  • “隐式防止所有形式的失败”
  • “避免了电流开关范围的混乱”
箭头( -> )指向返回值

使用JDK 12 Early Access Build ,可以方便地试用新的switch 表达式 ,我们还可以试用传统的和增强的switch 语句版本。

传统开关声明

即使启用了JDK 12预览( --enable-preview ),我们仍然可以使用我们“了解并爱着”的传统switch 语句 。 下面显示了这个传统 switch语句的示例,即使启用了JDK 12语言功能预览,该语句也可以成功编译和执行。

/*** Demonstrate traditional switch statement assigned to* local variable.*/
public static void demonstrateTraditionalSwitchStatement()
{out.println("Traditional Switch Statement:");final int integer = 3;String numericString;switch (integer){case 1 :numericString = "one";break;case 2 :numericString = "two";break;case 3:numericString = "three";break;default:numericString = "N/A";}out.println("\t" + integer + " ==> " + numericString);
}

这篇文章中显示的此代码以及所有其他代码示例可在GitHub上找到 。 这个特定的示例显示了传统switch语句设置局部变量值的常见用法。 我之所以选择此用例,是因为新的switch表达式是实现此目的的一种改进方法。

增强型开关声明

如前所述,我们可以在增强的 switch 语句中使用新的“箭头”语法(“带有开关标签的规则”)。 在使用--enalved-preview的JDK 12 Early Access Build 10上编译并运行的下一个代码示例中显示了这一点。

/*** Demonstrate enhanced switch statement used to assign* a local variable.*/
public static void demonstrateEnhancedSwitchStatement()
{out.println("Enhanced Switch Statement:");final int integer = 2;String numericString;switch (integer){case 1 -> numericString = "one";case 2 -> numericString = "two";case 3 -> numericString = "three";default -> numericString = "N/A";}out.println("\t" + integer + " ==> " + numericString);
}

最后一个示例显示了该switch仍然用作语句 ,但是在这种情况下,它利用了“箭头”语法(“标签规则”)来完成其切换,而没有明确指定break 。 这不仅减少了代码量,而且更重要的是具有不允许经常令人恐惧的switch “掉线”的优点。 简而言之, 增强后的 switch 语句的工作方式类似于当前/传统的switch语句,但是没有传统版本的潜在缺陷。

新开关表达式通过中断返回值

JEP 325除了增强当前的switch语句以允许指定switch语句而没有掉线的风险之外,还引入了在switch 表达式中使用switch关键字的概念。 Java教程的“ 表达式,语句和块 ”页面介绍了语句操作之间的区别。 为了便于讨论,该教程中的两个重要观察结果是(我加粗了强调):

  1. 表达式是由变量,运算符和方法调用组成的结构, 其结果为单个值 。”
  2. “ Java编程语言允许您从各种较小的表达式中构造复合表达式 ,只要该表达式的一部分所需的数据类型与另一部分的数据类型匹配即可。”

下一个代码清单演示了如何使用JDK 12 Early Access Build 10和--enable-preview替换上面显示的代码,该代码使用switch 语句将一个值分配给较早声明的局部变量,而该语句使用一个在单个语句中switch 表达式以将其结果值分配给局部变量。

/*** Demonstrate switch expression using colons and breaks.*/
public static void demonstrateSwitchExpressionWithBreaks()
{final int integer = 1;out.println("Switch Expression with Colons/Breaks:");final String numericString =switch (integer){case 1 :break "uno";case 2 :break "dos";case 3 :break "tres";default :break "N/A";};out.println("\t" + integer + " ==> " + numericString);
}

刚刚显示的代码示例演示了switch 表达式的使用,该表达式与前面显示的传统switch语句示例非常相似。 但是,有几个明显的不同。 区别在于此switch表达式返回的结果分配给局部变量“ numericString ”。 第二个区别直接与switch 表达式能够返回一个值有关,在于break子句现在每个都有要在break关键字后立即指定的相关case要返回的值。 本质上, switch 表达式break就像Java方法return

通过标签规则的新开关表达式返回值

只是示出的实施例表明,人们可以从一个返回值switch有类似结肠表达式: )和break语法什么一个很可能与使用switch的语句。 除了熟悉之外,此方法的另一个优点是可以在返回单个值之前为单个case指定多个语句。 但是,在大多数情况下,使用前面讨论的“箭头”语法从switch 表达式返回值可能会变得很流行,因为它不会遭受掉线的风险,并且可以避免通常与传统switch语句相关的范围意外。 下一个代码清单演示了新的switch 表达式如何使用“标签规则”(“箭头”语法)而不是冒号并break以优雅地返回该switch的单个解析值。

/*** Demonstrate switch expressions using "arrow" syntax.*/
public static void demonstrateSwitchExpressionWithArrows()
{final int integer = 4;out.println("Switch Expression with Arrows:");final String numericString =switch (integer){case 1 -> "uno";case 2 -> "dos";case 3 -> "tres";case 4 -> "quatro";default -> "N/A";};out.println("\t" + integer + " ==> " + numericString);
}

上面的四个示例演示了2×2网格中所示的每种情况。 本文的其余部分将讨论使用JDK 12 Early Access Build 10尝试switch表达式和语句时的一些其他观察结果。

可以为单个情况指定多个常量

2×2网格中的四个象限中的任何一个都允许将多个常数与单个case相关联。 在下一个代码清单中对此进行了演示,该清单在启用“预览语言功能”的情况下与JDK 12 Early Access Build 10一起编译和运行。

/*** Demonstrate that multiple constants can be associated with* a single {@code case} and used in conjunction with a* {@code switch} expression that uses the "arrow" syntax.*/
public static void demonstrateLabelRulesWithSharedCases()
{final int integer = 7;out.println("Multiple Case Labels:");final String numericString =switch (integer){case 0 -> "zero";case 1, 3, 5, 7, 9 -> "odd";case 2, 4, 6, 8, 10 -> "even";default -> "N/A";};out.println("\t" + integer + " ==> " + numericString);
}/*** Demonstrate that multiple constants can be associated with* a single {@code case} and used in conjunction with a* {@code switch} statement that uses the traditional colon and* {@code break} syntax.*/
public static void demonstrateBlockedStatementsWithSharedCases()
{final int integer = 6;out.println("Multiple Case Labels:");String numericString;switch (integer){case 0:numericString = "zero";break;case 1, 3, 5, 7, 9:numericString = "odd";break;case 2, 4, 6, 8, 10:numericString = "even";break;default:numericString = "N/A";};out.println("\t" + integer + " ==> " + numericString);
}

不能混用“箭头”(“标签规则”)和冒号/中断(“语句组”)

JDK 12 Early Access Build 10编译器( javac )不允许混合使用“箭头”语法和传统的冒号/ break语法。 尝试将这些混合使用会导致错误消息:“ 错误:开关中使用的种类不同 ”。 接下来显示了一个示例代码,该代码无法编译并显示此特定错误消息。

/*** WARNING - This does NOT compile, even with JDK 12 Early* Access Builds and --enable-preview because JEP 325 does* not allow the "arrow" syntax to be mixed with the* traditional colon/break syntax.*/
public static void demonstrateMixed()
{final int integer = 3;String numericString;switch(integer){case 1 :numericString = "one";break;case 2 -> numericString = "two";default -> numericString = "N/A";}return numericString;
}

Switch语句的中断无法返回值

新的switch 表达式返回一个值,当switch表达式使用冒号和break方法时,将在break关键字之后立即指定该返回值。 因为传统的switch 语句不返回值,所以尝试使与switch 语句关联的break指定返回值是编译时错误。 错误(“错误:意外的值中断”)可以用以下代码重现。

/*** WARNING - This does NOT compile, even with JDK 12 Early* Access Builds and --enable-preview because it is* nonsensical to have a "statement" return a value; that* is what an expression should be used for.*/
public static void demonstrateSwitchStatementReturnedLabel()
{final int integer = 4;switch (integer){case 1:break "one";case 2:break "two";case 3:break "three";default:break "N/A";};
}

当尝试使用带有指定标志--enable-preview-release 12 JDK 12 Early Access Build 10的javac编译器来编译以上代码时,错误消息“ error:意料之外 ”的四个实例(对应于三种case加上一种default价值突破 ”可见。 毫不奇怪,将switch分配给局部变量(并有效地将语句转换为表达式 )的简单更改就可以编译该代码。 换句话说,将上面的代码更改为下一个代码清单中的代码可以使其编译并成功运行。

/*** This demonstrates that a {@code switch} "expression" is* able to (and expected to) provide the "return" value for* a given {@code case} and {@code default} instead of being* a compiler error as it was for the "statement" example* demonstrated in method* {@link #demonstrateSwitchStatementReturnedLabel()}.*/
public static void demonstrateSwitchExpressReturnedLabel()
{final int integer = 4;final String numericString =switch (integer){case 1:break "one";case 2:break "two";case 3:break "three";default:break "N/A";};
}

当前的JEP 325文本包含有关此break行为与方法return相似的讨论。 该讨论指出, switch 语句在其break s之后不需要返回值的情况类似于返回void的方法。 switch 表达式应返回非void值。

Switch语句的“箭头”语法必须指向一条语句

即使向javac编译器提供了--enable-preview-release 12 ,以下代码也无法在JDK 12 Early Access Build 10中进行编译。

/*** WARNING - This does not compile, even with JDK 12 Early* Access Builds and --enable-preview and reports error message* "error: not a statement" because it is expecting a* {@code switch} "statement" but what is being provided to each* {@code case} is NOT a statement.*/
public static void demonstrateSwitchStatementReturnedValueViaLabelRule()
{final int integer = 5;switch (integer){case 1 -> "one";case 2 -> "two";};out.println(numericString);
}

上面的代码无法编译,并且报告的错误消息是“错误:不是语句”。 这是因为在此示例中将switch用作语句,但是“箭头”语法是“指向”文字字符串而不是有效的Java语句。

所有可能性都必须在switch表达式中指定

因为switch 表达式需要返回一个非void值,所以switch 表达式必须为其可能打开的所有可能值指定case 。 实际上,这很可能是通过default来实现的,以捕获未用case明确指定的所有可能性。 使用传统的switch语句,不需要确保所有可能打开的值都由casedefault值覆盖,并且有时会导致某些情况,例如我在博客文章“ Log Unexpected Switch Options ”中所述。

以下代码违反了以下规则: switch 表达式必须指定casedefault值的所有可能值:

/*** WARNING - This method will not compile even with JDK 12* Early Access Build 10 with --enable-preview because of* error; "the switch expression does not cover all possible* input values".*/
public static void demonstrateLackingCaseInSwitchExpression()
{final int integer = 5;String numericString =switch (integer){case 1 -> "one";case 2 -> "two";};out.println(numericString);
}

刚刚显示的代码将无法编译,并且因果错误消息为“错误:开关表达式未涵盖所有可能的输入值。”

JEP 325对交换机未来使用的影响

考虑到Java中除了switch 语句之外还有可用的switch 表达式所带来的可能性,并考虑到可以与switch表达式或语句一起使用的新“箭头”语法所提供的优势,开始思考何时进行有趣的事情。上面2×2网格中的每个象限最有利。 总的来说,我相信我会发现自己经常使用带有“箭头”语法(“标签规则”)的switch 表达式 ,同时也经常使用带有“ arrow”语法的增强型switch 语句 。 我怀疑将来我会很少使用传统的:break )语法。 即使在特定case有多个语句要执行时,我也可能会将这些语句分解为单个方法,在这种case使用“箭头”语法进行调用。 这将使我受益于更明显的作用域并避免掉线的风险。 鉴于现在可以为单个case指定多个常量,即使在多个案例导致相同结果的情况下,也不再需要穿透。

其他资源

  • JEP 325:开关表达式(预览)
  • JEP 325规范:开关表达式
  • JDK 12抢先体验版
  • JDK语言功能预览:切换表达式
  • 玩JDK 12的Switch表达式
  • 通过引入switch表达式来增强Java switch语句
  • 切换表达式到Java吗?
  • 切换表达式-收集线程
  • LJC演讲的少量反馈
  • GitHub上这篇文章的示例

翻译自: https://www.javacodegeeks.com/2018/09/jdk-12-switch-statements-expressions.html

JDK 12:实际中的切换语句/表达式相关推荐

  1. ubuntu安装jdk语句_JDK 12:实际中的切换语句/表达式

    ubuntu安装jdk语句 我的上一篇文章" 玩JDK 12的Switch表达式 "讨论了使用JDK 12 Early Access Builds尝试JEP 325 switch ...

  2. JDK 12开关表达式遇到意外的枚举值

    正如我在" 玩JDK 12的Switch表达式 "一文中所写的那样, JDK 12 Early Access Build使JEP 325的实现(" Switch Expr ...

  3. 【嵌入式】C语言高级编程-语句表达式(03)

    00. 目录 文章目录 00. 目录 01. C语言的表达式 02. C语言的语句 03. C语言中的代码块 04. C语言中的语句表达式 05. 宏中使用语句表达式 06. Linux内核应用示例 ...

  4. jdk8切换成jdk6_运行中的JDK语言功能预览:切换表达式

    jdk8切换成jdk6 JEP 12 ["预览语言和VM功能"]在其主页上描述如下: 预览语言或VM功能是Java SE平台的一项新功能,该功能已完全指定,完全实现但不是永久性的. ...

  5. Java SE 12扩展Switch语句/表达式完整指南

    本文提供了Java SE 12扩展Switch语句/表达式的完整指南.文章详细介绍了扩展Java switch语句将其用作增强版switch语句或表达式.为帮助理解本文提供了具体案例. 本文要点 现在 ...

  6. jdk12 switch_玩JDK 12的Switch表达式

    jdk12 switch 在博客文章"操作中的JDK语言功能预览:切换表达式 "中,我讨论了JEP 325 ["切换表达式( 预览 )")如何作为指定的&quo ...

  7. 玩JDK 12的Switch表达式

    在博客文章"操作中的JDK语言功能预览:切换表达式 "中,我讨论了JEP 325 ["切换表达式( 预览 )")如何作为指定的" 预览语言功能 &qu ...

  8. JDK语言功能预览:切换表达式

    JEP 12 ["预览语言和VM功能"]在其主页上描述如下: 预览语言或VM功能是Java SE平台的一项新功能,该功能已完全指定,完全实现但不是永久性的. JDK功能发布中提供了 ...

  9. c语言长度宏定义运算符,C语言在宏定义中使用语句表达式和预处理器运算符

    语句表达式的亮点在于定义复杂功能的宏.使用语句表达式来定义宏,不仅可以实现复杂的功能,而且还能避免宏定义带来的歧义和漏洞.下面以一个简单的最小值的宏为例子一步步说明. 1.灰常简单的么,使用条件运算符 ...

最新文章

  1. 数字图像处理:blob分析、阈值分割
  2. 高手都不用dw_雅诗兰黛DW粉底液好用吗?雅诗兰黛DW粉底液如何辨别真假?
  3. 基于 vue 的验证码组件
  4. knime二次开发节点的项目结构
  5. html打印日志_Graylog(四)使用Log4j2发送日志到Graylog
  6. pythonnet 引用_Python netmiko模块的使用
  7. 三级计算机信息安全基础知识
  8. A good article :csi cameras on the TX2 (the easy Way)
  9. java单词大全_编程常用英语单词大全
  10. Access to Image at 'file:///Users canvas本地图片跨域报错解决方案
  11. [数据库+python] 定时爬取B站日榜与微博热搜榜信息并保存至数据库
  12. Xprivacy - 必须拥有黑客应用程序
  13. Win11如何录屏?压箱底的录屏工具分享给你
  14. 王学岗视频编码————视频编解码基础与MediaCodec编解码(对应1234节)
  15. 这是一篇理工男写的口红科普文
  16. 系统背景描述_舞台灯光网络系统及光源角度资料免费分享
  17. ftp文件上传和下载
  18. 瞒不住了,Prefetch 就是一个大谎言
  19. 如何修改计算机软件id号,详解使用软件快手修改ID的操作流程
  20. 如何讲述个人职业生涯

热门文章

  1. Spark SQL(三)之视图与执行SQL
  2. 解决mybatis generator无法覆盖XML
  3. Javafx的WebEgine执行window对象设置属性后为undefined
  4. Spring整合mybatis中的sqlSession是如何做到线程隔离的?
  5. 深入浅出讲解语言模型
  6. mysql查询优化explain命令详解
  7. mybatis环境搭建步骤(含配置文件代码)
  8. 真正的问题应该在我身上……
  9. 新闻发布项目——接口类(categoryTBDao)
  10. 不同范数下的余弦定理_第06题 | 从源头追溯「余弦定理」amp; 文理科知识点的异同...