前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 8之后的那些新特性(七): switch表达式 Switch Expressions

Java 8之后的那些新特性(七): switch表达式 Switch Expressions

作者头像
御剑
发布2022-06-07 19:14:17
4.2K0
发布2022-06-07 19:14:17
举报
文章被收录于专栏:微言码道微言码道

对于Java程序员来说,switch语句应该是非常熟悉的了,它是Java中结构控制的一种。相信大家使用的都比较多了。

但其实在Java 12,13以及最终的17中,Java都引进与优化了与switch语句有关联的一个新特性,那就是switch表达式

这篇文章是Java 8之后的那些新特性系列的第七篇。本系列的其它文章为:

  1. 1. Java 8之后的那些新特性(一):局部变量var
  2. 2. Java 8之后的那些新特性(二):文本块 Text Blocks
  3. 3. Java 8之后的那些新特性(三):Java System Logger
  4. 4. Java 8之后的那些新特性(四):网络请求 Java Http Client
  5. 5. Java 8之后的那些新特性(五):Helpful NullPointerExceptions
  6. 6. Java 8之后的那些新特性(六):记录类 Record Class

从switch语句说起

要注意区分下,switch statement(switch语句)与switch expressions(switch表达式)两个词的不同。switch语句是大家熟悉的旧的switch用法,而 switch表达式则是我们今天要说的。

其实,从这两者之间的名字来看,就能猜到两者肯定有很大的相似性,也一定会有不同。

所以,要说switch表达式,我们一定得从switch语句说起。

public class SwitchTest {

    @Test
    void testSwitchStatement(){
        var trafficLight = randomTrafficLight();
        String lightString;
        switch (trafficLight){
            case LIGHT_RED: {
                lightString = "红灯";
                break;
            }
            case LIGHT_GREEN:{
                lightString = "绿灯";
                break;
            }
            case LIGHT_YELLOW: {
                lightString = "黄灯";
                break;
            }
            default: throw new IllegalArgumentException("不支持的信号灯");
        }
        Assertions.assertNotNull(lightString);
    }
}

上述代码应该是大家都非常熟悉的switch语句的代码。在讨论过往的switch语句时,无论大家看哪个教程,都一定会提醒大家一件事:

不要忘记break语句

否则switch语句的执行过程会出乎你的意料之外。

当然,随着Java的发展,switch语句出现了一些问题,有待改进。主要包括:

  • • 上面提及的break语句这个点,这个在设计上就非常糟糕
  • • switch语句不是表达式,通过switch语句覆值无法做到
  • • 对Java中最新的Pattern Matching无法支持

因此,这也是switch表达式出现的原因所在。switch表达式其实你可以认为它就是switch语句的改进版。它主要解决了switch语句在上述三个方面的问题。

switch表达式

好吧,我们用switch表达式来重写上面这个代码,你看到的效果将是这样

public class SwitchTest {

    @Test
    void testSwitchExpression(){
        var trafficLight = randomTrafficLight();
        var lightString = switch (trafficLight) {
            case LIGHT_YELLOW -> {
                yield  "黄灯";
            }
            case LIGHT_GREEN -> {
                yield  "红灯";
            }
            case LIGHT_RED -> {
                yield  "红灯";
            }
        };
        Assertions.assertNotNull(lightString);
    }
}

这是使用switch表达式来改写后的代码(这个可以再简化,但为了足够说明yield的作用,先这样)

通过上面这个改写,你可以很明显感知到,switch表达式可以做到:

  • • switch表达式是一个表达式,它有值返回的
  • • switch表达式并不需要break,这个点被改进了

而在switch表达式中,返回值是通过yield字段来处理的。并且,如果你只有一行返回值的情况下,可以省略掉block括号以及yield字段。

public class SwitchTest {
    @Test
    void testSwitchExpression(){
        var trafficLight = randomTrafficLight();
        var lightString = switch (trafficLight) {
            case LIGHT_YELLOW -> "黄灯";
            case LIGHT_GREEN -> "绿灯";
            case LIGHT_RED -> "红灯";
        };
        Assertions.assertNotNull(lightString);
    }
}

switch表达式的注意点

语法规则

注意,switch表达式的标准语法是

case label_1, label_2, ..., label_n -> expression;|throw-statement;|block 

switch表达式用的是 ->(箭头号),而在switch语句中,用的是: (冒号)

switch表达式必须穷尽一切可能

与switch语句不同,switch语句并不需要穷尽一切值,而switch表达式则一定要穷尽一切可能值,如果你不想穷尽所有值,可以使用default.

public class SwitchTest {
    @Test
    void testSwitchStatement(){
        var trafficLight = randomTrafficLight();
        String lightString = null;
        //switch语句可以不列出所有值,也可以没有default
        switch (trafficLight){
            case LIGHT_RED: {
                lightString = "红灯";
                break;
            }
            case LIGHT_GREEN:{
                lightString = "绿灯";
                break;
            }
        }
        Assertions.assertNotNull(lightString);
    }
}

但在switch表达式中,这是不允许的

public class SwitchTest {
    @Test
    void testSwitchExpression(){
        var trafficLight = randomTrafficLight();
        //这是不允许的,LIGHT_RED没有列上
        var lightString = switch (trafficLight) {
            case LIGHT_YELLOW -> "黄灯";
            case LIGHT_GREEN -> "绿灯";
        };
        Assertions.assertNotNull(lightString);
    }
}

上述代码会抛出编译错误:'switch' expression does not cover all possible input values

你可以加上case LIGHT_RED -> "红灯";或者使用default,这两种方式都可以。

switch表达式与Pattern Matching

上述只讲了switch表达式的两点,一个是它是表达式,二它不需要break,而switch表达式还可以搭配patten matching一同使用,做到模式自动匹配

这一点,我在下次再来说,聊一聊Pattern Matching这个新特性。

好了,这就是关于switch表达式的新特性,有了它,你可以忘掉过去那个会经常出错的switch语句了。

关于我

我是御剑,一个致力于实践与传播编码之道的全栈式程序员。

访问微言码道(https://taoofcoding.tech)以阅读更多我写的文章;

访问myddd(https://myddd.org)以了解我在维护的全栈式领域驱动开源框架。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微言码道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 从switch语句说起
  • switch表达式
  • switch表达式的注意点
  • switch表达式与Pattern Matching
  • 关于我
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档