你好,我是看山。
本文收录在 《从小工到专家的 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)的结果会是:
基于这种特性,我们可以合并多个值的执行逻辑,比如下面这种写法:
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 时,结果相同,都是:
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了。
青山不改,绿水长流,我们下次见。
推荐阅读
你好,我是看山。游于码界,戏享人生。如果文章对您有帮助,请点赞、收藏、关注。
评论