CodeGym /Java 博客 /China /Java switch 语句
作者
Milan Vucic
Programming Tutor at Codementor.io

Java switch 语句

已在 China 群组中发布

关于 Java switch 的一些理论知识

想象你是一名骑士,停在岔路口。如果向左走,则会失去马。如果向右走,则会获取知识。那么如何在代码中表示这种情况?你可能已经知道我们使用 if-thenif-then-else 等结构来做出这些决定。

if (turn_left) { 
    System.out.println("You will lose your horse"); 
}
if (turn_right) {
    System.out.println("You will gain knowledge");
}
else 
    System.out.println("So you're just going to stand there?");

如果这条路不是分成两条,而是分成十条呢?则你的路有“完全靠右”、“稍微靠左”、“靠左一点”等,总共有 10 条可能的路? 想像一下你的“if-then-else”代码在这种情况下要增加多长!

if (option1)
{…}
else if (option2)
{…}
…
else if (optionN) ...
假设路上有一个 10 分叉(重要的是,选项的数量是有限的)。对于这种情况,Java 提供了 switch 语句。

       switch (ExpressionForMakingAChoice) {
           case (Value1):
               Code1;
               break;
           case (Value2):
               Code2;
               break;
...
           case (ValueN):
               CodeN;
               break;
           default:
               CodeForDefaultChoice;
               break;
       }

下面是该语句的工作方式:
  • 对 ExpressionForMakingAChoice 求值。然后 switch 语句将结果值与下一个 ValueX 进行比较(按列出的顺序)。
  • 如果 ExpressionForMakingAChoice 与 ValueX 匹配,则执行冒号后面的代码。
  • 如果遇到 break 语句,则将控制转移到 switch 语句之外。
  • 如果 ExpressionForMakingAChoice 与任何 ValueX 都不匹配,则控制传递给 CodeForDefaultCase。
要点
  • 在 switch 语句中,ExpressionForMakingAChoice 的类型必须是以下之一:

    • byteshortcharint
    • ByteShortCharacterInteger(原始数据类型的包装类)。
    • String
    • Enum
  • default 块是可选的。如果此块不存在并且 ExpressionForMakingAChoice 与任何 ValueX 都不匹配,则不会执行任何操作。

  • 不需要 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;
}
请注意,我们对大气成分相同的行星使用相同的代码。我们通过使用连续的 case 语句来做到这一点。 如果想得到我们母星的大气成分,我们将 3 作为参数调用方法:

getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) returns ["Carbon dioxide", "Nitrogen", "Oxygen"].
试验 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)) 的结果,那么我们会发现我们的母星不是那么宜居。或宜居吗?自行判断:
["二氧化碳", "氮气", "氧气", "氢气", "氦气", "甲烷", "氢气", "氦气"]。
为何发生这种情况?在第一次匹配后,该程序会执行所有的 case 语句,直到 switch 块结束。

过度优化 break 语句

请注意,我们可以通过以不同方式排列 break 语句和 case 来改进该方法。

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;
}
看起来代码少了,对吧?我们通过调整 case 语句的顺序并重新组合来减少语句的总数。现在,每种类型的气体都添加到列表中,一种气体一行代码。 最后一个例子中给出的代码只是为了展示原理的。我们建议以这种方式编写代码。如果此类 Java 代码的作者(更不用说其他程序员)必须进行维护,会发现很难重构这些 case 块形成背后的逻辑以及在 switch 语句中执行的代码。

与 if 的区别

鉴于 ifswitch 语句表面很相似,不要忘记 switch 语句根据特定值选择一个 case,而 if 语句可以使用任何布尔表达式。在设计代码时请记住这一点。 Java switch 语句 - 1

结论

  • case 语句用于两个以上的分支,以免你的代码与 if 语句混淆。
  • 不要忘记通过插入 break 语句来完成每个特定值(case 语句)的分支逻辑块。
  • switch 语句的表达式可以是 EnumString,以及一些原始类型。
  • 记住 default 块。使用它来处理意外的值。
  • 要优化性能,请将与最常见值对应的代码分支移动到 switch 块的开头。
  • 不要删除 case 语句末尾的 break 语句而执着于“优化” — 这样的代码很难理解,因此也很难维护。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION