06 | switch表达式:怎么简化多情景操作?
- 深入了解
- 翻译
- 解释
- 总结
Java 14引入了switch表达式这一新特性,它在处理多情景操作时能够简化代码逻辑和提高效率。相比传统的switch语句,switch表达式更加灵活,能够作为一个表达式返回值,而不仅仅是一个语句。文章通过一个计算月份天数的案例展示了传统switch语句的使用,指出了在使用过程中容易出现的错误和不便之处。为了解决这些问题,Java引入了switch表达式,使得多情景处理的代码块能够变成一个表达式,从而简化了代码逻辑和提高了可读性。通过引入switch表达式,Java语言在处理多情景操作时变得更加灵活和高效。在新的switch表达式中,出现了箭头标识符和yield关键字,使得多情景的合并更加简洁,消除了传统switch语句中容易出现的错误和冗余代码。此外,改进的switch语句也可以使用箭头标识符,不再需要显式的break语句来实现情景间的代码共享,从而提高了代码的可维护性和可读性。总的来说,Java 14中引入的switch表达式为多情景操作提供了更加灵活和高效的解决方案,极大地简化了代码逻辑,提高了代码的可读性和可维护性。文章还提出了对新特性的思考题,引发读者对于代码设计的深入思考。
《深入剖析 Java 新特性》,新⼈⾸单¥59
全部留言(12)
- 最新
- 精选
- fatme终于明白思考题的思路,原来是要在编译期暴露出问题。这种思路,即使是对 jdk 8 以下也是有用的,只不过是不像 switch 表达式一样有语言本身的帮助。又学了一招,谢谢老师!
作者回复: 不谢。
2021-12-022 - ABC第一个问题是: 我们现在的代码能够检测到这个变化吗?如果不能,是不是只有系统崩溃的时候,我们才能够意识到问题的存在? 答: 如果是新增的月份现在的设计只能抛出异常,提醒我们修改代码.如果是减少了月份,在未更新JDK的情况下,代码正常运行.另外: JDK并非强更新,有些用户并不会频繁更新JDK,在我接触的一些项目,甚至还在使用JDK1.6,因此对于新特性和漏洞的修复,反应很迟缓. 第二个问题是,有没有更健壮的设计,能够帮助我们在系统崩溃之前就能够检测到这个意想不到的变化?从而给我们留出时间更改我们的代码和系统? 答: 持续关注JDK漏洞修复和版本发布,及时升级.这样所遇到的错误会第一时间反馈给我们,以留给我们修复问题的时间. 题外话,本来准备用java.time.LocalDate重写一下获取月份天数,想提交一个pr.发现用LocalDate来写,就三行代码.提pr有点太寒酸了,就发在这把(笑~) import java.time.LocalDate; var localDate=LocalDate.now(); // 判断是否为闰年. var isleapYear=localDate.isLeapYear(); System.out.println(localDate.getMonth().length(isleapYear)); 下面这段代码来自java.time.Month.class,这样判断感觉: public int length(boolean leapYear) { switch (this) { case FEBRUARY: return (leapYear ? 29 : 28); case APRIL: case JUNE: case SEPTEMBER: case NOVEMBER: return 30; default: return 31; } } 可以改写为: public int length(boolean leapYear) { return switch (this) { case FEBRUARY -> (leapYear ? 29 : 28); case APRIL, JUNE, SEPTEMBER, NOVEMBER -> 30; default -> 31; }; }
作者回复: “就三行代码,提pr有点太寒酸了”,多小的改动都不会显得寒酸。任何一个开源社区,都需要很多小的改动。
2021-11-2652 - aoe->好用很多,switch 变好看了
作者回复: 好看就是生产力!
2021-11-262 - 猿人谷这个新特性看着很不错!
作者回复: 它应该是我们以后使用switch的标准。
2021-11-262 - xiaobang第二个问题,感觉可以用枚举类型来表示月份,这样switch表达式检查到没有穷举到全部值
作者回复: 是的,如果月份的API重新设计的话,一定是使用枚举而不是整数来表达。
2021-11-271 - 自然这里的 yield ,仅是 类似return的功能么?还是有多线程里的 yield 含义和用处?
作者回复: 可以使用return的类比来理解。只是,返回的是表达式的值,而不是退出一个方法。
2022-05-10 - 第二少关于本讲思考题,如果要在编译期间检测出Calendar类增加了第十三个月,关键就是要有一种机制能穷举Calendar类里面定义的所有月份,比如可以用枚举来实现预定义的月份,就可以穷举了;然后对于 switch(x),只要 x 对应的值是可穷举的,那么jdk 17的编译器已经支持检查 x 对应的值在case里有没有全部被覆盖了,如果没有全部覆盖,就会报编译错误: java: switch 表达式不包含所有可能的输入值 如果是在ide里,不需要手动执行编译,就会有错误提示;如果编译器本身不支持做这种检查,那也可以充分利用ide来检查错误,比如IntellJ IDEA,可以自定义对应的inspections来做到这一点
作者回复: idea是个很好的工具。
2021-12-25 - aoe今天《极客时间》两个专栏同时更新,主题都是 switch - 《深入剖析 Java 新特性》06 | Switch表达式:怎么简化多情景操作? - 《Tony Bai · Go 语言第一课》20|控制结构:Go中的switch语句有哪些变化? 对比结果 - Java17 居然可以比 Go 简洁! - 但然综合能力 Go 的更灵活 Java17 switch ```java String checkWorkday(int day) { return switch (day) { case 1, 2, 3, 4, 5 -> "it is a work day"; case 6, 7 -> "it is a weekend day"; default -> "are you live on earth"; }; } ``` Go switch ```go func checkWorkday(day int) string { switch day { case 1, 2, 3, 4, 5: return "it is a work day" case 6, 7: return "it is a weekend day" default: return "are you live on earth" } } ```
作者回复: “综合能力 Go 的更灵活”,该怎么理解?从你给出的例子没有看出来。
2021-11-267 - Jxin1.既然知道是一个弊大于利的方案,为何 switch表达式 还要使用 冒号标识符 来保留fall-through的模式? switch表达式 区别于 switch语句,可没有兼容问题。 2.猜测使用 -> 而不是 : 。应该是为了区别 switch语句 : 的语义,同时对称 Lambda 风格的表达方式。 3. switch语句 本身好像直接被归为坏味道,不建议使用(eff里看到的还是哪,忘了)。建议直接用 if卫语句/map策略模式 来替换。 switch表达式 从使用上来看,个人觉得语义上比 if卫语句/map策略模式都要清晰,使用这个写法可以提高阅读效率。唯一可惜的是case后面无法支持表达式,所以实际使用场景就会很受限(这个适用范围也跟编码设计能力有关,要用还是可以用的,只是没有支持表达式来的简单易用)。 课后题: 1.不能,第十三个月会获取不到天数,这好像不算是系统崩溃,只能说出bug才知道。 2.在 DaysInMonth 追加一个 一个 static 代码块(方法有很多),校验日期枚举实例是否超过12,超过告警。 这样至少在项目启动能感知到。
作者回复: 1. 如果反对的声音再多一点, 这个冒号的表达式形式可能就没了。 2. 需要和冒号的形式区别开来。 3. 能够支持有限的表达式啊。 再看看下一讲吧, 里边有相关的话题。
2021-11-26 - 大胖子呀、第一个问题,目前的程序可以检测到多了一个月份,会通过最后的default语句抛出异常,但是检测不到少了一个月份; 第二个问题,我想着是否可以在default表达式里,通过遍历Calendar枚举的元素,去匹配出Calendar.AFTERDEC,但是我有疑问的是:月份多出了一个月,它的出现是否会导致已有月份的计算方式的改变?它的计算方式是按照31、30天,还是按照2月份,又或者是一个崭新的计算方式?这一块我确实不知道该如何在代码中实现,求老师指点。
作者回复: 1. 多一个月检测到的方式是运行时抛出异常,这需要测试代码的配合,不能等到实际运行阶段。少一个月份,通常这个月份,比如FEBRUARY,就会从API里删除掉,这样编译时就可以检测出来了。 2. 你的疑问可以通过自己进一步的假设解决,你可以使用30/31/28,或者另外的一个你喜欢的数。
2021-11-26