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