JavaRush /Java 博客 /Random-ZH /Java中的switch语句

Java中的switch语句

已在 Random-ZH 群组中发布
想象一下,你站在一个岔路口,就像名画中的英雄一样。如果你向左走,你就会失去马;如果你向右走,你就会获得知识。遇到这样的情况该如何编程呢?您很可能已经知道我们使用if-thenif-then-else结构做出这样的选择。
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
如果这样的轨道不是两条而是 10 条怎么办?有没有“向右”、“向左一点”、“向左再一点”等等的路径,数量为 10 条?想象一下您的if-then-else代码在此版本中将如何增长!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
所以,你没有一个分叉条件,而是几个,比如说 10 个(这里重要的是分叉的数量是有限的)。对于这种情况,有一个特殊的选择运算符 - switch case java
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
语句中的执行顺序如下:
  • 对 SelectionExpression 进行求值。接下来,switch 语句将结果表达式与下一个值(按列出的顺序)进行比较。
  • 如果 SelectExpression 与 Value 匹配,则执行冒号后面的代码。
  • 如果遇到中断结构,则控制权将转移到 switch 命令之外。
  • 如果在 ExpressionForSelection 和 Values 之间没有找到匹配项,则控制权将转移到 DefaultSelectionCode。
要点
  • Java 中 switch 选择语句的 SelectionExpression 类型必须是以下之一:

    • 字节整型、字符整型
    • 它们的包装器是 ByteShortCharacterInteger
    • 字符串(自 Java 7 起)。
    • 枚举(Enum)。
  • 默认块是可选的,那么如果SelectionExpression和Values不匹配,则不会执行任何操作。
  • break是可选的;如果它不存在,代码将继续执行(忽略 case 块中值的进一步比较)直到break遇到第一个 switch 语句或直到结束。
  • 如果需要对多个选择选项执行相同的代码,为了避免重复,我们在连续的case块中在其前面指示几个对应的值。

下面我们继续进行Java中switch语句的使用实践

别担心,我们已经完成了理论,在进一步的示例之后,一切都会变得更加清晰。那么让我们开始吧。让我们看一个关于太阳系行星的天文学例子。根据最新的国际法规,我们将排除冥王星(由于其轨道的特性)。让我们记住,我们的行星从太阳开始的位置顺序如下:水星、金星、地球、火星、木星、土星、天王星和海王星。让我们创建一个 Java 方法,该方法接收行星的序列号(相对于距太阳的距离)作为输入,并以 List <String> 的形式生成该行星大气层的主要成分作为输出。让我提醒您,一些行星具有相似的大气成分。因此,金星和火星主要含有二氧化碳,木星和土星由氢和氦组成,天王星和海王星除了最后一对气体外还含有甲烷。我们的职能:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
            break;
        case 2:
        case 4: result.add("Carbon dioxide");
            break;
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
            break;
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
            break;
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
            break;
        default:
            break;
    }
    return result;
}
请注意:我们将相同的代码与具有相同大气成分的行星进行了比较。我们通过使用连续的案例结构来做到这一点。因此,如果我们想获取我们家乡星球的大气成分,我们可以使用参数 3 调用我们的方法:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
尝试break如果我们删除所有break语句 会发生什么?让我们在实践中尝试一下:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
        case 2:
        case 4: result.add("Carbon dioxide");
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
        default:
    }
    return result;
}
如果我们打印出该方法的结果System.out.println(getPlanetAtmosphere(3)),那么我们的家园星球将不再那么适合生命存在。或者适合吗?自己判断一下: [二氧化碳、氮气、氧气、氢气、氦气、甲烷、氢气、氦气], 为什么会发生这种情况?程序在第一个匹配之后执行所有情况,直到 switch 块结束。

优化中断过多

请注意,我们可以通过不同的中断指令和选择选项排列 来改进该方法
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
                break;
        case 3: result.add("Nitrogen");
                result.add("Oxygen");
        case 2:
        case 4: result.add("Carbon dioxide");
                break;
        case 7:
        case 8: result.add("Methane");
        case 5:
        case 6: result.add("Hydrogen");
                result.add("Helium");
    }
     return result;
}
看起来更短,不是吗?我们通过调整案例顺序和重新分组来减少语句总数。现在,只需一行代码即可将每种类型的气体添加到列表中。该方法的最后一个示例的列表仅用于演示工作;强烈不建议以这种风格编写。如果类似代码的作者(更何况第三方程序员)必须维护它,那么恢复java switch语句的选择块形成逻辑和可执行代码将非常困难。

与 if 的区别

虽然ifswitch语句在外观上很相似 ,但不要忘记,多项选择运算符 switch 根据特定值来选择执行选项,而在 if 中。可以是任何逻辑表达式。设计代码时请考虑这一事实。让我们仔细看看不同版本的 Java 中 switch 的创新。

Java 7 中的切换

在 Java 7 之前,byte、short、char 和 int 原语可以用作 switch 的值。还支持上面列出的基本类型的枚举和包装器:字符、字节、短整型和整数。但我们经常需要找到java switch字符串的值!这就是 Java 6 中的样子:
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
和枚举:
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
但从 Java 7 开始,可以使用 String 类型作为 switch 的值:
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
尽管有新功能,但使用枚举的方法更加灵活,建议使用:我们可以多次重用这个枚举。

Java 12 中的切换

Java 12 改进了用于模式匹配的 Switch 表达式。如果我们像上面的例子一样使用 Switch,要设置某个变量的值,我们必须计算该值并将其分配给给定的变量,然后使用break:
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
但借助 Java 12 的功能,我们可以将这个表达式重写如下:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
让我们稍微回顾一下这些变化:
  1. 如果以前我们在case块中设置一个变量值,由于switch语句本身无法返回任何内容,现在我们有这样的机会,我们可以直接使用switch返回值。

  2. 以前,我们不能再在 Break 右侧添加任何内容,但现在我们使用它作为 return 语句来返回 switch 的值。冒号标记标记语句块的入口点。也就是说,从那时起,即使遇到另一个标签,也会开始执行下面的所有代码。

    结果是从一个标记到另一个标记的端到端转换,也称为失败

Java中的switch语句 - 2要完成这样的遍历,您必须完全遍历所有元素,或者使用break或return。java 12 中的创新使我们能够使用 lambda 运算符,这反过来又确保只有其右侧的代码才会被执行。没有任何“失败”。在这种情况下,前面的示例会是什么样子:
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
代码变得简单多了,不是吗?还有一件事:lambda 运算符也可以充当冒号的典型类似物,之后是一个包含一些操作的整个块:
int count = 2;
int value = switch (count) {
  case 1 -> {
     //some computational operations...
     break 12;
  }
  case 2 -> {
     //some computational operations...
     break 32;
  }
  case 3 -> {
     //some computational operations...
     break 52;
  }
  default -> {
     //some computational operations...
     break 0;
  }
};
那么,如果在某些情况下返回值是相同的怎么办?事实证明,对于某些不同的值,我们实际上有相同的情况。以下是如何使用 Java 12 中的新功能来缩短这一时间:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Java 13 中的切换

在 Java 13 中,开关返回值的方式发生了变化。如果在java 12中我们在break之后写了返回值,它作为我们switch块的返回,现在我们将使用单词yield返回该值。我们看看吧:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
同时,在java 12中使用break返回的代码将无法编译(( Java中的switch语句 - 3会使用Break,但在我们不需要返回任何内容的情况下。

全部的

  • 当存在两个以上分支时,请使用case语句,以避免 if 结构使代码变得混乱。
  • 不要忘记用break调用结束与特定值(case块)对应的每个分支的逻辑块。
  • switch 语句除了可以使用一些基本类型之外,还可以使用EnumString类型作为表达式 。
  • 记住默认块- 使用它来处理计划外的选择值。
  • 为了优化性能,请将具有最常见选择的代码分支移至 switch 块的开头。
  • 不要通过删除案例选择块末尾的中断来进行“优化” ——这样的代码很难理解,因此在开发过程中很难维护。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION