關於 Java Switch 的一些理論
想像一下,你是一個停在岔路口的騎士。如果你向左走,你會失去你的馬。如果你走對了,你將獲得知識。我們如何在代碼中表示這種情況?您可能已經知道我們使用if-then和if-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 的類型必須是以下之一:
- 字節、短、字符、整數。
- Byte、Short、Character、Integer(原始數據類型的包裝)。
- 字符串。
- 枚舉。
- 默認塊是可選的。如果它不存在並且 ExpressionForMakingAChoice 不匹配任何 ValueX,則不會執行任何操作。
- 不需要break語句。如果它不存在,代碼將繼續執行(忽略 case 語句中的進一步比較)直到第一次出現break或直到switch語句結束。
- 如果需要為多個選擇執行相同的代碼,我們可以通過指定幾個連續的case語句來消除重複。
現在讓我們看看 switch 語句在 Java 中是如何使用的
別擔心:我們已經完成了理論。看到下面的例子之後,一切都會變得更加清晰。好吧,讓我們開始吧。讓我們看一個涉及我們太陽系行星的天文學例子。根據最新的國際態度,我們排除了冥王星(由於其軌道的特性)。我們記得我們的行星按它們與太陽的距離排列如下:水星、金星、地球、火星、木星、土星、天王星和海王星。讓我們編寫一個 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 的區別
考慮到if和switch語句的外在相似性,不要忘記switch語句根據特定值選擇一種情況,而 if 語句可以有任何布爾表達式。在設計代碼時請記住這一點。結論
- 對兩個以上的分支使用case語句,以免 if 語句使您的代碼混亂。
- 不要忘記通過插入break語句來完成每個特定值(case 語句)的分支邏輯塊。
- switch語句的表達式可以是Enum或String,以及一些原始類型。
- 記住默認塊。用它來處理意外值。
- 為了優化性能,將與最常見值對應的代碼分支移動到switch塊的開頭。
- 不要通過刪除case語句末尾的break語句來進行“優化” ——這樣的代碼很難理解,因此也很難維護。
GO TO FULL VERSION