Java核心技术速学版(第3版)
上QQ阅读APP看书,第一时间看更新

1.7.2 switch语句

switch表达式的功能是将一个操作数与多个选项进行比较,并为每个具体情况生成一个值:

String seasonName = switch (seasonCode) { // switch expression
     case 0 -> "Spring";
     case 1 -> "Summer";
     case 2 -> "Fall";
     case 3 -> "Winter";
     default -> {
          System.out.println("???");
          yield "";
     }
};

需要注意的是,switch在这里是一个表达式(expression),并且有一个值,即5个字符串"Spring" "Summer""Fall""Winter"""中的一个。这个switch表达式的值被赋值给seasonName变量。

其实最常见的情况是,一个case后面跟着一个表达式。你也可以在一个花括号括起来的语句块中做一些其他的额外工作,就像前面示例中的default部分一样。然后,你需要在语句块中使用yield语句来生成一个值。

switch还有一种语句形式,如下所示:

switch (seasonCode) { // switch statement
     case 0 -> seasonName = "Spring";
     case 1 -> seasonName = "Summer";
     case 2 -> seasonName = "Fall";
     case 3 -> seasonName = "Winter";
     default -> {
          System.out.println("???");
          seasonName = "";
     }
}

在前面的示例中,case标签是整数。你可以使用以下任意类型的值:

char类型、byte类型、short类型或int类型的常量表达式(或与其相对应的封装类Character、Byte、Short和Integer,将在1.8.3小节中介绍);

字符串字面量;

枚举的值(参见第4章)。

每个case都可以有多个标签,并用逗号分隔:

int numLetters = switch (seasonName) {
     case "Spring", "Summer", "Winter" -> 6;
     case "Fall" -> 4;
     default -> throw new IllegalArgumentException();
}; 

注意:整数或String上的switch表达式总是有一个default部分。无论操作数值是什么,switch表达式都必须生成一个值。此外,如前一个示例所示,大小写的区别可能会引发异常。异常将在第5章中具体介绍。

警告:如果switch的操作数值为null,那么一个NullPointerException异常将会被抛出。当操作数类型为String或枚举时,会发生这种情况。

在前面的示例中,switch表达式和语句中,对于给定的操作数值只有一个case分支被执行。当然有时也可能会发生一些例外,这种情况通常被称作直通(fall-through,也称贯通)。即其从匹配的case分支开始执行,然后继续执行下一个case,除非被yield或break语句打断。switch的直通式变体同样也具有表达式和语句形式。在下面的示例中,当seasonName为"Spring"时会发生这种直通。

int numLetters = switch (seasonName) { // switch expression with fall-through
    case "Spring":
        System.out.println("spring time!");
    case "Summer", "Winter":
        yield 6;
    case "Fall":
        yield 4;
    default:
        throw new IllegalArgumentException();
};
 
switch (seasonName) { // switch statement with fall-through
    case "Spring":
        System.out.println("spring time!");
    case "Summer", "Winter":
        numLetters = 6;
        break;
     case "Fall":
        numLetters = 4;
        break;
    default:
        throw new IllegalArgumentException();
}

需要注意的是,在直通式变体中,每个 case后面都跟一个冒号,而不是一个 ->。这样可以在冒号后跟任意数量的语句,并且不需要花括号。此外,在带有直通的switch表达式中,必须使用yield来生成一个值。

警告:在直通式变体中,忘记yield或break是一个常见的错误。除非真的需要直通行为,否则请避免使用这种变体。