if-else 與 switch 是 Java 兩大核心選擇結構。雖然功能有重疊,但適用場景、性能特徵、可讀性、擴展性存在本質差異。本文從語法、執行流程、字節碼、最佳實踐四個維度深度對比。
if (condition1) {
// statement block 1
} else if (condition2) {
// statement block 2
} else if (condition3) {
// statement block 3
} else {
// default block
}
boolean 表達式 (比較、邏輯運算、方法調用)switch (expression) {
case value1:
// statements
break; // 關鍵:防止貫穿
case value2:
case value3: // 合並 case
// statements
break;
default:
// default statements
}
byte/short/char/int (及包裝類)enumStringswitch 表達式 (箭頭語法,無 break,返回值)tableswitch/lookupswitch 指令,近似 O(1) 跳轉判斷 condition1 → true → 執行塊1 → 結束
↓ false
判斷 condition2 → true → 執行塊2 → 結束
↓ false
...
↓ false
執行 else 塊 → 結束
計算 expression 值
↓
查找匹配 case (哈希/索引跳轉)
↓
匹配 → 執行該 case 及後續所有代碼 (直到 break/結束)
↓
無匹配 → 執行 default (若有) → 結束
| 維度 | if-else | switch |
|---|---|---|
| 判斷類型 | boolean 表達式 (任意複雜度) | 離散值匹配 (常量、enum、String) |
| 區間判斷 | ✅ 原生支持 (score >= 90 && score <= 100) | ❌ 不支持 (需轉換為多個 case) |
| 性能 (大量分支) | O(n) 線性判斷 | O(1) 跳轉表 (編譯器優化) |
| 代碼可讀性 | 少量分支清晰,多層嵌套混亂 | 多固定值分支極其清晰 |
| 維護擴展 | 修改條件靈活 | 新增 case 簡單,但類型固定 |
| 貫穿特性 | 無 | 有 (忘寫 break 是高頻 Bug) |
| 返回值 (JDK 12+) | 三元運算符/方法調用 | switch 表達式直接返回 |
// ✅ if-else 完美契合
if (score >= 90) grade = 'A';
else if (score >= 80) grade = 'B';
else if (score >= 70) grade = 'C';
else if (score >= 60) grade = 'D';
else grade = 'E';
// ❌ switch 極其別扭 (需枚舉所有分數)
switch (score) {
case 100: case 99: ... case 90: grade='A'; break;
case 89: ... case 80: grade='B'; break;
// 101 個 case!
}
// ✅ switch 清晰高效
switch (day) {
case 1: return "周一";
case 2: return "周二";
// ...
case 7: return "周日";
default: throw new IllegalArgumentException("無效星期: " + day);
}
// JDK 12+ 表達式寫法 (更簡潔)
String dayName = switch (day) {
case 1 -> "周一";
case 2 -> "周二";
// ...
default -> throw new IllegalArgumentException("無效: " + day);
};
String browser = "Chrome";
switch (browser) {
case "Chrome": case "Firefox": case "Edge": return "現代瀏覽器";
case "IE": return "舊版瀏覽器";
default: return "未知";
}
// 注意:switch String 內部用 hashCode + equals,性能優於 if-else 鏈
if_icmpge, if_icmplt 等比較跳轉指令,線性檢查tableswitch:索引表直接跳轉,極快lookupswitch:二分查找鍵值對,仍優於線性hashCode() + lookupswitch + equals() 確認,仍優於長鏈 if-elsecondition ? a : b| 錯誤 | 代碼 | 後果 | 修正 |
|---|---|---|---|
| 忘寫 break | case 1: ... case 2: ... | 貫穿執行,邏輯錯誤 | 必寫 break,或 JDK 12+ 箭頭語法 |
| case 用變量 | case myVar: | 編譯錯誤 | 用 final 常量或 if-else |
| switch long/float/double | switch (1.0) | 編譯錯誤 | 轉 int 或用 if-else |
| String switch 空指針 | switch (nullStr) | NPE (JDK 11-), JDK 12+ 可匹配 null | 先判空或升級 JDK |
if-else 是萬能選擇結構,switch 是離散值匹配的專用優化工具。記住口訣:**區間找 if-else,離散值用 switch,字符串枚舉 switch 更強,JDK 12 表達式更香,別忘 break 防貫穿,null 判斷 if 更穩**。根據業務語義選擇,代碼才能既高效又優雅。