JavaRush /Java Blog /Random-TW /Java中的switch語句

Java中的switch語句

在 Random-TW 群組發布
想像一下,你站在一個岔路口,就像名畫中的英雄一樣。如果你向左走,你就會失去馬;如果你向右走,你就會獲得知識。遇到這樣的情況該如何程式設計呢?您很可能已經知道我們使用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