想象一下,你站在一个岔路口,就像名画中的英雄一样。如果你向左走,你就会失去马;如果你向右走,你就会获得知识。遇到这样的情况该如何编程呢?您很可能已经知道我们使用if-then和if-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 类型必须是以下之一:
- 字节、短整型、字符、整型。
- 它们的包装器是 Byte、Short、Character、Integer。
- 字符串(自 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 的区别
虽然if和switch语句在外观上很相似 ,但不要忘记,多项选择运算符 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;
};
让我们稍微回顾一下这些变化:
-
如果以前我们在case块中设置一个变量值,由于switch语句本身无法返回任何内容,现在我们有这样的机会,我们可以直接使用switch返回值。
-
以前,我们不能再在 Break 右侧添加任何内容,但现在我们使用它作为 return 语句来返回 switch 的值。冒号标记标记语句块的入口点。也就是说,从那时起,即使遇到另一个标签,也会开始执行下面的所有代码。
结果是从一个标记到另一个标记的端到端转换,也称为失败。
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返回的代码将无法编译(( 会使用Break,但在我们不需要返回任何内容的情况下。
全部的
- 当存在两个以上分支时,请使用case语句,以避免 if 结构使代码变得混乱。
- 不要忘记用break调用结束与特定值(case块)对应的每个分支的逻辑块。
- switch 语句除了可以使用一些基本类型之外,还可以使用Enum和String类型作为表达式 。
- 记住默认块- 使用它来处理计划外的选择值。
- 为了优化性能,请将具有最常见选择的代码分支移至 switch 块的开头。
- 不要通过删除案例选择块末尾的中断来进行“优化” ——这样的代码很难理解,因此在开发过程中很难维护。
GO TO FULL VERSION