for、while 迴圈


在Java中如果要進行重複性指令執行,可以使用for迴圈式,基本語法之一如下:

for(初始式; 執行結果必須是boolean的重複式; 重複式) {
    陳述句;
}

for迴圈語法的圓括號中,初始式只執行一次,所以通常用來宣告或初始變數,如果是宣告變數,結束for迴圈後變數就會消失。第一個分號後則是每次執行迴圈本體前會執行一次,且必須是true或false的結果,true就會執行迴圈本體,false就會結束迴圈,第二個分號後,則是每次執行完迴圈本體後會執行一次。

實際來看個for迴圈範例,在文字模式下從1顯示到10:

package cc.openhome;

public class OneToTen {
    public static void main(String[] args) {
        for(int i = 1; i <= 10; i++) {
            System.out.println(i);
        }
    }
}

這個程式白話讀來,就是從i等於1,只要i小於等於10就執行迴圈本體(顯示i),然後遞增i,這是for迴圈的常見的應用方式。如果for本體只有一行陳述句,則{與}可以省略,不過為了可讀性與可維護性而言,現在建議是就算只有一行陳述句,也要撰寫{與}明確定義範圍。

在介紹for迴圈時,許多書籍或文件很喜歡用的範例就是顯示九九乘法表,這邊就用這個例子來示範:

package cc.openhome;

public class NineNineTable {
    public static void main(String[] args) {
        for(int j = 1; j < 10; j++) { 
           for(int i = 2; i < 10; i++) { 
               System.out.printf("%d*%d=%2d ",i, j,  i * j);
           } 
           System.out.println(); 
        }  
    }
}

執行結果如下:

2*1= 2 3*1= 3 4*1= 4 5*1= 5 6*1= 6 7*1= 7 8*1= 8 9*1= 9
2*2= 4 3*2= 6 4*2= 8 5*2=10 6*2=12 7*2=14 8*2=16 9*2=18
2*3= 6 3*3= 9 4*3=12 5*3=15 6*3=18 7*3=21 8*3=24 9*3=27
2*4= 8 3*4=12 4*4=16 5*4=20 6*4=24 7*4=28 8*4=32 9*4=36
2*5=10 3*5=15 4*5=20 5*5=25 6*5=30 7*5=35 8*5=40 9*5=45
2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 7*6=42 8*6=48 9*6=54
2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 8*7=56 9*7=63
2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 9*8=72
2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81

事實上,for迴圈語法只是將三個複合陳述區塊寫在圓括號中而已,第一個陳述區塊只會執行一次,第二個陳述區塊專司判斷是否繼續下一個迴圈,而第三個陳述區塊只是一般的陳述句。

for圓括號中的每個陳述區塊是以分號;作區隔,而在一個陳述區塊中若想寫兩個以上的陳述句,則使用逗號,作區隔,有興趣的話,研究一下底下九九乘法表的寫法,只使用了一個for迴圈就可以完成九九乘法表列印,執行結果與上一個範例相同(就可讀性而言,並不建議這麼寫):

package cc.openhome;

public class NineNineTable2 {
    public static void main(String[] args) {
        for (int i = 2, j = 1;  j < 10; i = (i==9)?((++j/j)+1):(i+1)) { 
            System.out.printf("%d*%d=%2d%c", i, j,  i * j, (i==9 ? '\n' : ' '));
        }   
    }
}

for
迴圈圓括號中第二個複合陳述區塊若沒有撰寫,預設就是true。所以偶而你看到有人如下撰寫的話,表示無窮迴圈:

for(;;) {
    ...
}

for中包括一個if陳述時:

for(...) {
    if(condMatched) {
        ...
    }
}

由於Java是個自由格式語言,去掉第一個for迴圈的{},並將if排版在for右邊,就會看來像是這樣:

for(...) if(condMatched) {
    ...
}

偶而你會看到有這種風格的寫法,讓程式閱讀看來流暢一些。

Java提供while迴圈,可根據指定條件式來判斷是否執行迴圈本體,語法如下所示:

while(條件式) {
    陳述句;
}

如果迴圈本體只有一個陳述句,則while{}可以省略不寫,但為了可讀性,建議還是撰寫。while主要用於停止條件必須在執行時期判斷的重複性動作,例如在一個使用者輸入介面,使用者可能輸入的學生名稱個數未知,只知道要結束時會輸入quit,就可以使用while迴圈。

底下是個很無聊的遊戲,看誰可以最久不撞到這個數字5:

package cc.openhome;

public class RandomStop {
    public static void main(String[] args) {
        while(true) {
            int number = (int) (Math.random() * 10);
            System.out.println(number);
            if(number == 5) {
                break;
            }
        }
        System.out.println("I hit 5....Orz");
    }
}

這個範例的while判斷式直接設為true,表示每次while重來就直接執行迴圈本體,Math.random()會隨機產生0.0到小於1.0的值,乘上10再裁掉小數部份,表示產生0到9的數,在while迴圈中如果執行到break,會離開迴圈本體。

一個參考的執行結果如下:

9
5
I hit 5....Orz

while迴圈有時稱為前測式迴圈,因為會在迴圈執行前就進行條件判斷,如果想先執行一些動作,再判斷要不要重複,則可以使用do..while,又稱為後測式迴圈,do..while的語法如下所示:

do {
    陳述句;
} while(條件式);

注意while後面是以分號 ;作為結束,這個很常被忽略;可以將上一個範例改為do..while,可以少寫一個boolean判斷:

package cc.openhome;

public class RandomStop2 {
    public static void main(String[] args) {
        int number;
        do {
            number = (int) (Math.random() * 10);
            System.out.println(number);
        } while(number != 5);
        System.out.println("I hit 5....Orz");
    }
}

RandomStopwhileif兩個需要boolean判斷的地方,這主要是因為一開始number的值並沒有產生,所以只好先進入while迴圈。使用do..while,先產生number,再判斷要不要執行迴圈,剛好可以解決這個問題。