? ? ? ? 就像有感知的生物一樣,程序必須在執行過程中控制它的世界,并做出選擇。在Java中,你要使用執行控制語句來作出選擇。
一、流程控制基礎概念
1.1 流程控制的重要性
????????流程控制結構決定了程序執行的順序和邏輯分支,是編程語言中最基礎也是最重要的組成部分。Java繼承了C/C++的大多數流程控制結構,但去除了一些容易出錯的部分(如goto語句),并增加了一些安全性檢查。
1.2 Java中的流程控制分類
????????Java中的流程控制主要分為三類:
條件語句:if-else, switch-case
循環語句:while, do-while, for, 增強for循環
流程中斷語句:break, continue, return
二、條件語句
2.1 if-else語句
????????if-else是最基礎的條件分支結構,語法如下:
if (布爾表達式) {// 表達式為true時執行
} else {// 表達式為false時執行
}
2.1.1 多條件分支
????????可以嵌套使用if-else實現多條件分支:
if (condition1) {// condition1為true時執行
} else if (condition2) {// condition2為true時執行
} else {// 其他情況執行
}
2.1.2 注意事項
布爾表達式必須返回boolean類型(與C/C++不同,不能使用數值)
即使只有一條語句,也建議使用花括號(提高可讀性和避免錯誤)
else與最近的if匹配
2.2 switch語句
????????switch用于多值選擇,語法如下:????????
switch (表達式) {case 值1:// 代碼塊1break;case 值2:// 代碼塊2break;default:// 默認代碼塊
}
2.2.1 switch特性
表達式類型可以是:
基本類型:byte, short, char, int
包裝類:Byte, Short, Character, Integer
枚舉類型
String(Java 7+)
case值必須是編譯時常量
需要break語句防止"貫穿"(fall-through)現象
default分支是可選的
2.2.2 Java 12+的switch表達式
????????Java 12引入了更簡潔的switch表達式語法:
int numLetters = switch (day) {case MON, FRI, SUN -> 6;case TUE -> 7;case THU, SAT -> 8;case WED -> 9;default -> throw new IllegalStateException();
};
三、循環語句
3.1 while循環
????????while循環在條件為真時重復執行代碼塊:
while (布爾表達式) {// 循環體
}
3.1.1 注意事項
循環體可能一次都不執行(先檢查條件)
需要確保循環條件最終會變為false,否則會導致無限循環
循環體內通常應修改影響循環條件的變量
3.2 do-while循環
????????do-while循環先執行一次循環體,再檢查條件:
do {// 循環體
} while (布爾表達式);
3.2.1 與while的區別
循環體至少執行一次
分號不能省略
3.3 for循環
????????for循環提供了更緊湊的循環語法:
for (初始化; 布爾表達式; 步進) {// 循環體
}
3.3.1 for循環執行流程
執行初始化表達式(僅一次)
檢查布爾表達式:
如果為true,執行循環體
如果為false,退出循環
執行步進表達式
重復步驟2-3
3.3.2 特殊形式
可以省略初始化、布爾表達式或步進(但分號不能省略)
可以在初始化部分聲明多個變量(類型相同)
可以在初始化部分使用已有變量
for (int i = 0, j = 10; i < j; i++, j--) {System.out.println(i + " " + j);
}
3.4 增強for循環(for-each)
????????Java 5引入的增強for循環簡化了數組和集合的遍歷:
for (元素類型 變量名 : 數組或集合) {// 使用變量名訪問元素
}
3.4.1 特點
更簡潔的語法
避免使用顯式索引
不能修改原數組/集合元素(對于基本類型數組)
不能獲取當前索引
3.4.2 實現原理
????????增強for循環對數組和Iterable接口的實現類處理方式不同:
數組:編譯為基于索引的標準for循環
Iterable:使用iterator()方法獲取迭代器
四、流程中斷語句
4.1 break
????????break用于:
退出switch語句的case塊
提前終止循環
4.1.1 帶標簽的break
????????Java支持標簽(label)語法,可以跳出多層嵌套循環:
outer:
for (int i = 0; i < 10; i++) {for (int j = 0; j < 10; j++) {if (i * j > 50) {break outer; // 跳出外層循環}}
}
4.2 continue
????????continue跳過當前循環的剩余部分,直接開始下一次循環:
for (int i = 0; i < 10; i++) {if (i % 2 == 0) {continue; // 跳過偶數}System.out.println(i);
}
4.2.1 帶標簽的continue
????????類似break,continue也可以使用標簽:
outer:
for (int i = 0; i < 10; i++) {for (int j = 0; j < 10; j++) {if (j > i) {continue outer; // 跳到外層循環的下一次迭代}System.out.println(i + " " + j);}
}
4.3 return
????????return用于從方法中返回:
無返回值方法:直接返回
有返回值方法:返回指定值
public int max(int a, int b) {if (a > b) {return a;}return b;
}
五、特殊流程控制
5.1 嵌套循環
????????循環可以多層嵌套,但應注意:
嵌套層次不宜過深(通常不超過3層)
內層循環應盡可能簡單
考慮使用帶標簽的break/continue簡化控制
5.2 遞歸
????????方法可以調用自身,形成遞歸:
public int factorial(int n) {if (n <= 1) {return 1;}return n * factorial(n - 1);
}
5.2.1 遞歸注意事項
必須有終止條件
每次遞歸應使問題規模減小
Java默認的調用棧深度有限(可通過-Xss參數調整)
遞歸可能比迭代效率低
六、Java與C/C++流程控制的區別
布爾表達式:Java必須使用boolean類型,不能使用數值
goto語句:Java沒有goto,但標簽+break/continue可以實現類似功能
for循環變量作用域:Java可以在for初始化部分聲明變量,作用域限于循環
增強for循環:Java特有的簡化語法
switch語句:
Java 7+支持String
case值必須是編譯時常量
必須有break防止貫穿(除非有意為之)
七、最佳實踐與常見陷阱
7.1 最佳實踐
代碼塊始終使用花括號:即使只有一條語句
switch語句始終包含default分支:處理未預期的值
避免深層嵌套:使用方法提取或提前返回簡化邏輯
循環條件應明顯可見:避免隱藏的無限循環
優先使用增強for循環:當不需要索引時
7.2 常見陷阱
if語句缺少花括號:
if (condition)statement1;statement2; // 無論condition如何都會執行
switch貫穿問題:
switch (x) {case 1: System.out.println("1");case 2: System.out.println("2"); // 當x=1時也會執行 }
浮點數比較:
for (double d = 0.1; d != 1.0; d += 0.1) {// 可能因浮點精度問題導致無限循環 }
修改增強for循環的集合:
for (String s : list) {list.remove(s); // 拋出ConcurrentModificationException }
八、現代Java中的流程控制改進
8.1 Java 14的switch表達式(正式版)
????????Java 14使switch表達式成為正式特性:
int numLetters = switch (day) {case MON, FRI, SUN -> 6;case TUE -> 7;case THU, SAT -> 8;case WED -> {System.out.println("Wednesday");yield 9; // 使用yield返回值}default -> 0;
};
8.2 模式匹配(預覽特性)
????????Java 14+引入了模式匹配的預覽特性:
// instanceof模式匹配(Java 16正式)
if (obj instanceof String s) {System.out.println(s.length()); // 直接使用s
}// switch模式匹配(預覽)
switch (obj) {case Integer i -> System.out.println("Integer: " + i);case String s -> System.out.println("String: " + s);default -> System.out.println("Other");
}
九、foreach設計哲學
9.1 設計目標
簡化迭代語法:隱藏迭代器細節
統一訪問方式:數組和集合使用相同語法
減少錯誤:避免越界和修改異常
9.2?foreach修改集合問題
List<String> list = new ArrayList<>();
// 錯誤方式(拋出ConcurrentModificationException)
for (String s : list) {if (s.equals("remove")) list.remove(s);
}// 正確方式1:使用迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()) {if (it.next().equals("remove")) it.remove();
}// 正確方式2:Java 8+ removeIf
list.removeIf(s -> s.equals("remove"));
9.3?多維數組遍歷優化
// 低效方式(多次數組訪問)
for (int i = 0; i < matrix.length; i++) {for (int j = 0; j < matrix[i].length; j++) {sum += matrix[i][j];}
}// 高效方式(緩存行數組)
for (int[] row : matrix) {for (int val : row) {sum += val;}
}
結語:通過深入理解這些流程控制機制,我們可以編寫出更高效、更健壯的Java代碼,同時為適應Java語言的持續演進做好準備。