写点什么

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

作者:看山
  • 2022 年 6 月 19 日
  • 本文字数:2922 字

    阅读完需:约 10 分钟

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"); } }}
复制代码


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

Switch 块通用语法

switch(integral-selector) {case value1: statement1; break;case value2: statement2; break;// ……default: default-statement;}
复制代码


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");        }    }}
复制代码


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


012
复制代码


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


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");        }    }}
复制代码


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


0 or 1 or 2
复制代码

Switch 表达式

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


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


@Testvoid 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());}
复制代码


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


@Testvoid 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);}
复制代码


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


@Testvoid 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);}
复制代码

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)));}
复制代码


结果是:


nullString 1int 2long 3double 4.000000AtomicLong 5
复制代码


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


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

推荐阅读


你好,我是看山。游于码界,戏享人生。如果文章对您有帮助,请点赞、收藏、关注。

发布于: 刚刚阅读数: 7
用户头像

看山

关注

🏆 InfoQ写作平台-签约作者 🏆 2017.10.26 加入

InfoQ签约作者,CSDN 博客专家,公号「看山的小屋」,专注后端开发、架构相关知识分享,个人网站 https://howardliu.cn/。

评论

发布
暂无评论
Switch 块、Switch 表达式、Switch 模式匹配,越来越好用的 Switch_Java_看山_InfoQ写作社区