• Switch 块、Switch 表达式、Switch 模式匹配,越来越好用的 Switch


    Switch 块、Switch 表达式、Switch 模式匹配,越来越好用的 Switch

    你好,我是看山。

    本文收录在 《从小工到专家的 Java 进阶之旅》 系列专栏中。

    与 if-else 一样,switch 语法是用来做条件判断的。当条件清晰简洁时,能够有效地提升代码可读性。switch 语法从 Java5 开始,Java12 增加了 Switch 表达式(Java14 提供正式版),Java17 增加 Switch 模式匹配(预览版)。

    本文的目标是期望读者可以掌握 Switch 语法的所有能力,在需要的时候信手拈来。

    if-else 与 switch 语法

    我们先来个简单的例子看看 if-else 和 switch 语法的使用:

    public static void demoOfIf(int num) {
        if (num == 0) {
            System.out.println("0");
        } else if (num == 1) {
            System.out.println("1");
        } else if (num == 2) {
            System.out.println("2");
        } else {
            System.out.println("3");
        }
    }
    
    public static void demoOfSwitch(int num) {
        switch (num) {
            case 0: {
                System.out.println("0");
                break;
            }
            case 1: {
                System.out.println("1");
                break;
            }
            case 2: {
                System.out.println("2");
                break;
            }
            default: {
                System.out.println("3");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    上面的示例很简单,下面我们就来着重学习一下 Swith 语法。

    Switch 块通用语法

    switch(integral-selector) {
    case value1: statement1; break;
    case value2: statement2; break;
    // ……
    default: default-statement;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    switch 语句是一种多路选择的简洁表达式,在 Java7 之前,switch 语句的表达式必须是整数值,这样会有很多的限制。于是在 Java7 中增加了 String 格式的支持,使应用场景更加丰富。

    每个 case 执行语句末尾都有一个break关键字,它会让执行流程跳到 switch 的末尾。如果不加break,后面的 case 语句会继续执行,直到第一个break关键字。

    比如:

    public static void noBreak(int num) {
        switch (num) {
            case 0: {
                System.out.println("0");
            }
            case 1: {
                System.out.println("1");
            }
            case 2: {
                System.out.println("2");
                break;
            }
            default: {
                System.out.println("3");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    执行noBreak(0)的结果会是:

    0
    1
    2
    
    • 1
    • 2
    • 3

    基于这种特性,我们可以合并多个值的执行逻辑,比如下面这种写法:

    public static void noBreak2(int num) {
        switch (num) {
            case 0:
            case 1:
            case 2: {
                System.out.println("0 or 1 or 2");
                break;
            }
            default: {
                System.out.println("3");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    当参数是 0 或 1 或 2 时,结果相同,都是:

    0 or 1 or 2
    
    • 1

    Switch 表达式

    Switch 语句出现的姿势是条件判断、流程控制组件,与现在很流行的新语言对比,其写法显得非常笨拙,所以 Java 推出了 Switch 表达式语法,可以让我们写出更加简化的代码。这个扩展在 Java12 中作为预览版首次引入,需要在编译时增加-enable-preview开启,在 Java14 中正式提供,功能编号是 JEP 361

    比如,我们通过 switch 语法简单计算工作日、休息日,在 Java12 之前需要这样写:

    @Test
    void testSwitch() {
        final DayOfWeek day = DayOfWeek.from(LocalDate.now());
        String typeOfDay = "";
        switch (day) {
            case MONDAY:
            case TUESDAY:
            case WEDNESDAY:
            case THURSDAY:
            case FRIDAY:
                typeOfDay = "Working Day";
                break;
            case SATURDAY:
            case SUNDAY:
                typeOfDay = "Rest Day";
                break;
        }
    
        Assertions.assertFalse(typeOfDay.isEmpty());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在 Java12 中的 Switch 表达式中,我们可以直接简化:

    @Test
    void testSwitchExpression() {
        final DayOfWeek day = DayOfWeek.SATURDAY;
        final String typeOfDay = switch (day) {
            case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";
            case SATURDAY, SUNDAY -> "Day Off";
        };
    
        Assertions.assertEquals("Day Off", typeOfDay);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    是不是很清爽。不过,这里有一点不足的是,如果是需要执行一段业务逻辑,然后返回一个结果呢?于是 Java13 使用yield关键字补齐了这个功能:

    @Test
    void testSwitchExpression13() {
        final DayOfWeek day = DayOfWeek.SATURDAY;
        final String typeOfDay = switch (day) {
            case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
                System.out.println("Working Day: " + day);
                yield "Working Day";
            }
            case SATURDAY, SUNDAY -> {
                System.out.println("Day Off: " + day);
                yield "Day Off";
            }
        };
    
        Assertions.assertEquals("Day Off", typeOfDay);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Switch 模式匹配

    到 Java17 时,又提供了 Switch 模式匹配功能。与 instanceof 模式匹配有些类似,是能够在 Switch 表达式实现类型自动转换。

    比如:

    static String formatterPatternSwitch(Object o) {
        return switch (o) {
            case null -> "null";
            case Integer i -> String.format("int %d", i);
            case Long l -> String.format("long %d", l);
            case Double d -> String.format("double %f", d);
            case String s -> String.format("String %s", s);
            default -> o.getClass().getSimpleName() + " " + o;
        };
    }
    
    public static void main(String[] args) {
        System.out.println(formatterPatternSwitch(null));
        System.out.println(formatterPatternSwitch("1"));
        System.out.println(formatterPatternSwitch(2));
        System.out.println(formatterPatternSwitch(3L));
        System.out.println(formatterPatternSwitch(4.0));
        System.out.println(formatterPatternSwitch(new AtomicLong(5)));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    结果是:

    null
    String 1
    int 2
    long 3
    double 4.000000
    AtomicLong 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看到,不只是类型自动转换,还可以直接判断是否是null,省了前置判断对象是否是null了。

    青山不改,绿水长流,我们下次见。

    推荐阅读


    你好,我是看山。游于码界,戏享人生。如果文章对您有帮助,请点赞、收藏、关注。我还整理了一些精品学习资料,关注公众号「看山的小屋」,回复“资料”即可获得。

    个人主页:https://www.howardliu.cn
    个人博文:Switch 块、Switch 表达式、Switch 模式匹配,越来越好用的 Switch
    CSDN 主页:https://kanshan.blog.csdn.net/
    CSDN 博文:Switch 块、Switch 表达式、Switch 模式匹配,越来越好用的 Switch

    👇🏻欢迎关注我的公众号「看山的小屋」,领取精选资料👇🏻
  • 相关阅读:
    声纹技术(二):音频信号处理基础
    C语言习题~day32
    嵌入式必学,硬件资源接口详解——基于ARM AM335X开发板 (上)
    Taro 封装箭头组件
    @SpringBootApplication配置了scanBasePackages导致请求一直404,分析下原因
    基于PHP+MySQL简历模板下载管理系统
    云计算项目七:jump-server安装部署
    C/C++基础
    【我的前端】面向 JavaScript 开发:前端必学的4种函数式编程技术
    每日学习笔记:C++ STL 的forward_list
  • 原文地址:https://blog.csdn.net/conansix/article/details/126069533