• fatme
    2021-12-02
    终于明白思考题的思路,原来是要在编译期暴露出问题。这种思路,即使是对 jdk 8 以下也是有用的,只不过是不像 switch 表达式一样有语言本身的帮助。又学了一招,谢谢老师!

    作者回复: 不谢。

    
    2
  • ABC
    2021-11-26
    第一个问题是: 我们现在的代码能够检测到这个变化吗?如果不能,是不是只有系统崩溃的时候,我们才能够意识到问题的存在? 答: 如果是新增的月份现在的设计只能抛出异常,提醒我们修改代码.如果是减少了月份,在未更新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有点太寒酸了”,多小的改动都不会显得寒酸。任何一个开源社区,都需要很多小的改动。

    共 5 条评论
    2
  • aoe
    2021-11-26
    ->好用很多,switch 变好看了

    作者回复: 好看就是生产力!

    
    2
  • 猿人谷
    2021-11-26
    这个新特性看着很不错!

    作者回复: 它应该是我们以后使用switch的标准。

    
    2
  • xiaobang
    2021-11-27
    第二个问题,感觉可以用枚举类型来表示月份,这样switch表达式检查到没有穷举到全部值

    作者回复: 是的,如果月份的API重新设计的话,一定是使用枚举而不是整数来表达。

    
    1
  • 自然
    2022-05-10
    这里的 yield ,仅是 类似return的功能么?还是有多线程里的 yield 含义和用处?

    作者回复: 可以使用return的类比来理解。只是,返回的是表达式的值,而不是退出一个方法。

    
    
  • 第二少
    2021-12-25
    关于本讲思考题,如果要在编译期间检测出Calendar类增加了第十三个月,关键就是要有一种机制能穷举Calendar类里面定义的所有月份,比如可以用枚举来实现预定义的月份,就可以穷举了;然后对于 switch(x),只要 x 对应的值是可穷举的,那么jdk 17的编译器已经支持检查 x 对应的值在case里有没有全部被覆盖了,如果没有全部覆盖,就会报编译错误: java: switch 表达式不包含所有可能的输入值 如果是在ide里,不需要手动执行编译,就会有错误提示;如果编译器本身不支持做这种检查,那也可以充分利用ide来检查错误,比如IntellJ IDEA,可以自定义对应的inspections来做到这一点

    作者回复: idea是个很好的工具。

    
    
  • aoe
    2021-11-26
    今天《极客时间》两个专栏同时更新,主题都是 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 的更灵活”,该怎么理解?从你给出的例子没有看出来。

    共 7 条评论
    
  • Jxin
    2021-11-26
    1.既然知道是一个弊大于利的方案,为何 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,或者另外的一个你喜欢的数。

    
    