Java程式設計拾遺『控制流程』
與任何程式設計語言一樣,Java使用條件語句和迴圈結構確定控制流流程。
1. 條件語句
條件語句就是使用if進行條件判斷,及邏輯處理,主要包含以下幾種形式。
1.1 if
單if條件語句格式如下:
if (condition) {
statement;
}
如果布林表示式condition為真,則執行statement語句。
1.2 if……else
if……else條件語句格式如下:
if (condition) {
statement1;
} else {
statement2;
}
如果布林表示式condition為真,則執行statement語句,否則執行statement語句。
1.3 if……else if……else
if……else if……else條件語句格式如下:
if (condition) {
statement1;
} else if (condition1) {
statement2;
} else {
statement3;
}
如果布林表示式condition為真,則執行statement1語句,條件語句結束。否則判斷condition1是否為真,如果為真則執行statement2語句。如果condition與condition都不為真,則執行statement語句。else if條件可以有多個,一旦從上到下其中一個布林表示式檢測為 true,則執行該布林表示式的語句,其他的 else if 以及 else 語句都將跳過執行。假如所有的布林表示式都為false,則最終執行else中的語句。
1.4 巢狀的if…else
if語句中可以隨意巢狀其它格式的條件語句,但是建議最好不要巢狀太多曾,不然程式碼可讀性會比較差。
if(condition1) {
statement1;
if(condition1) {
statement2;
}
}
2. 迴圈語句
Java中存在一下三種主要的迴圈結構,for迴圈結構、while迴圈結構、do…while迴圈結構。對於這三種迴圈結構,熟悉C/C++的人應該很清楚它們的語義。迴圈結構主要用於迴圈處理控制。
2.1 for迴圈
for迴圈主要存在三種形式,如下:
2.1.1 普通for迴圈
for(initialization; boolean-expression; step) { statement; }
- 最先執行initialization。可以宣告一種型別,初始化一個或多個迴圈控制變數,也可以是空語句。
- 然後,檢測boolean-expression的值。如果為 true,迴圈體被執行。如果為false,迴圈終止,開始執行迴圈體後面的語句。
- 執行一次迴圈後,根據step更新迴圈控制變數。
- 再次檢測布林表示式。迴圈執行上面的過程。
2.1.2 增強for迴圈
Java5中引入了一種主要用於陣列或者實現了Iterable介面的類物件的增強型for迴圈,用來依次處理陣列中的每一個元素,而不用指定具體的陣列角標。
for(type variable-name : collection) {
statement;
}
增強for迴圈丟掉了索引資訊,當遍歷集合或陣列時,如果需要訪問集合或陣列的下標,只能使用普通for迴圈。
2.1.3 Java8 forEach迴圈
Java8中結合Lambda表示式,引入一種新的for迴圈,用於實現了Iterable介面的類物件的迴圈遍歷,forEach方法是集合父介面java.lang.Iterable中新增的一個default實現方法。不瞭解Lambda表示式的同學可以參考我之前的一篇文章 Java8函數語言程式設計
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
2.2 while迴圈
while迴圈是最基本的迴圈結構,結構為:
while(boolean-expression) {
statement;
}
只要布林表示式為true,迴圈就會一直執行下去。假如第一次判斷布林表示式就為false,那麼迴圈體一次都不會被執行
2.3 do…while迴圈
do…while 迴圈和 while 迴圈相似,不同的是,對於while迴圈而言,如果布林表示式條件,則不能進入迴圈體,而do…while迴圈至少會執行一次迴圈體。
do {
statement;
}while(boolean-expression);
2.4 迴圈流程控制
在進行迴圈時,有時候需要根據一定的條件終止迴圈。Java提供兩種方式終止迴圈,分別是break和continue。
2.4.1 break
break用於中斷當前迴圈,存在兩種形式,一種是單break形式,另一種是break label形式。區別在於break只能中斷當前迴圈,而不能終端外層迴圈,如果想中斷外層迴圈,只能通過break label的方式。
2.4.1.1 break
@Test
public void breakTest(){
for (int i = 0; i < 3; i++) {
System.out.println(String.format("start outer for loop index %d", i));
for (int k = 0; k < 3; k++) {
if (k == 1){
break;
}
System.out.println(String.format("inner loop index %d", k));
}
System.out.println(String.format("end outer for loop index %d", i));
}
System.out.println("loop end");
}
執行結果:
start outer for loop index 0
inner loop index 0
end outer for loop index 0
start outer for loop index 1
inner loop index 0
end outer for loop index 1
start outer for loop index 2
inner loop index 0
end outer for loop index 2
loop end
可以看出break中斷了內層迴圈,但是外層迴圈依然可以正常執行
2.4.1.2 break label
C++中有一個goto關鍵字,可以將邏輯跳轉到相應的label。Java中goto只是一個保留字,並不是關鍵字,也沒有相應的語義。但在java中可以通過break label達到類似的效果。
@Test
public void breakLabelTest(){
BREAK_LABEL:
for (int i = 0; i < 3; i++) {
System.out.println(String.format("start outer for loop index %d", i));
for (int k = 0; k < 3; k++) {
if (k == 1){
break BREAK_LABEL;
}
System.out.println(String.format("inner loop index %d", k));
}
System.out.println(String.format("end outer for loop index %d", i));
}
System.out.println("loop end");
}
執行結果:
start outer for loop index 0
inner loop index 0
loop end
可以看出break BREAK_LABEL中斷了外層迴圈。
2.4.2 continue
break會中斷離break關鍵字最近的迴圈體的迴圈,而continue只會終止本次迴圈,並進行本迴圈體的下一次迴圈。另外,跟break相似,continue也有兩種形式,一種是單continue形式,另一種是continue label形式。
2.4.2.1 continue
@Test
public void continueTest(){
for (int i = 0; i < 3; i++) {
System.out.println(String.format("start outer for loop index %d", i));
for (int k = 0; k < 3; k++) {
if (k == 1){
continue;
}
System.out.println(String.format("inner loop index %d", k));
}
System.out.println(String.format("end outer for loop index %d", i));
}
System.out.println("loop end");
}
執行結果:
start outer for loop index 0
inner loop index 0
inner loop index 2
end outer for loop index 0
start outer for loop index 1
inner loop index 0
inner loop index 2
end outer for loop index 1
start outer for loop index 2
inner loop index 0
inner loop index 2
end outer for loop index 2
loop end
可以看出continue終止了k==1時的內層迴圈
2.4.2.2 continue label
@Test
public void continueLabelTest(){
CONTINUE_LABEL:
for (int i = 0; i < 3; i++) {
System.out.println(String.format("start outer for loop index %d", i));
for (int k = 0; k < 3; k++) {
if (k == 1){
continue CONTINUE_LABEL;
}
System.out.println(String.format("inner loop index %d", k));
}
System.out.println(String.format("end outer for loop index %d", i));
}
System.out.println("loop end");
}
執行結果:
start outer for loop index 0
inner loop index 0
start outer for loop index 1
inner loop index 0
start outer for loop index 2
inner loop index 0
loop end
“end outer for loop index”這一行沒有列印,說明continue label終止了外層迴圈,並進行下一次迴圈。
3. switch語句
switch語句看一看作一種特殊的條件語句,這裡在控制流程中順帶講述一下。
switch(expression){
case value1 :
statement1;
break; //可選
case value :
statement2;
break; //可選
//可以有任意數量的case語句
default : //可選
statement3;
}
- switch 語句中的變數型別可以是: byte、short、int 或者 char。從 Java SE 7 開始,switch 支援字串 String 型別了,同時 case 標籤必須為字串常量或字面量。
- switch 語句可以擁有多個 case 語句。每個 case 後面跟一個要比較的值和冒號。
- case 語句中的值的資料型別必須與變數的資料型別相同,而且只能是常量或者字面常量。
- 當變數的值與 case 語句的值相等時,那麼 case 語句之後的語句開始執行,直到 break 語句出現才會跳出 switch 語句。
- 當遇到 break 語句時,switch 語句終止。程式跳轉到 switch 語句後面的語句執行。case 語句不必須要包含 break 語句。如果沒有 break 語句出現,程式會繼續執行下一條 case 語句,直到出現 break 語句。
- switch 語句可以包含一個 default 分支,該分支一般是 switch 語句的最後一個分支(可以在任何位置,但建議在最後一個)。default 在沒有 case 語句的值和變數值相等的時候執行。default 分支不需要 break 語句。