現實生活中待解決的事千奇百怪,在電腦發明之後,想要使用電腦解決的需求也是各式各樣:「如果」發生了…,就要…;「對於」…,就一直執行…;「如果」…,就「中斷」…。為了告訴電腦在特定條件下該執行的動作,您要會使用各種條件式來定義程式執行的流程。
為了應付「如果」發生了 …,就要 … 的需要,Java 提供了 if 條件式 ,它的語法如下:
if(條件式)
陳述句一;
else
陳述句二;
這個語法的意思,白話來說,就是當「條件式」成立時(true),則執行「陳述句一」,要不然(else)就執行「陳述句二」;如果條件式不成立時並不想作任何事,則 else 可以省略。
在 if 後如果有兩個以上陳述句,稱之為「複合陳述句」(Compound statement),此時必須使用 { } 定義區塊(Block)將複合陳述句包括起來,例如:
if(條件式) {
陳述句一;
陳述句二;
}
else {
陳述句三;
陳述句四;
}
範例 3.25 是個簡單的程式,使用if條件式來判斷使用者的輸入是奇數還是偶數。
import java.util.Scanner;
public class OddDecider3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入數字: ");
int input = scanner.nextInt();
int remain = input % 2; // 求除 2 的餘數
if(remain == 1) // 如果餘數為1
System.out.println(input + "為奇數");
else
System.out.println(input + "為偶數");
}
}
在 if 中您也可以再設定執行的條件,例如:
if(條件式一) {
陳述句一;
if(條件式二)
陳述句二;
陳述句三;
}
這只個簡單的例子,其中陳述句二要執行,必須同時滿足「條件式一」與「條件式二」才行;再來看個例子:
if(條件式一) {
陳述句一;
// 其它陳述句
}
else
if(條件式二)
陳述句二;
如果「條件式一」不滿足,就會執行 else 中的陳述,而您在這邊進行「條件式二」的測試,如果滿足就執行「陳述句二」,由於 Java 是個自由格式語言,您可以適當的排列這個程式,這會比較好懂一些:
if(條件式一) {
陳述句一;
// 其它陳述句
}
else if(條件式二)
陳述句二;
基於這個方式,您可以如下設定多個條件,且易讀易懂:
if(條件式一)
陳述一;
else if(條件式二)
陳述句二;
else if(條件式三)
陳述句三;
else
陳述句四;
「陳述句四」會在條件式一、二、三都不成立時執行;範例3.26是個簡單的例子,處理學生的成績等級問題。
import java.util.Scanner;
public class ScoreLevel {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("輸入分數:");
int score = scanner.nextInt();
if(score >= 90)
System.out.println("得A");
else if(score >= 80 && score < 90)
System.out.println("得B");
else if(score >= 70 && score < 80)
System.out.println("得C");
else if(score >= 60 && score < 70)
System.out.println("得D");
else
System.out.println("得E(不及格)");
}
}
執行結果如下:
輸入分數:88
得B
在這邊要注意的是 if 與 else 的配對問題,例如以下程式依縮排來看,您覺得有無問題存在?
if(條件式一)
if(條件式二)
陳述句一;
else
陳述句二;
很多人都會以為「條件式二」的 if 會與 else 配對,但事實上是「條件式一」的 if 與 else 配對,加上括號的話就不會誤會了:
if(條件式一) {
if(條件式二)
陳述句一;
else
陳述句二;
}
如果想避免這種錯誤,在程式中多使用括號是必要的,多寫一些總是比少寫一些來得保險一點。
注意到了嗎?在撰寫程式時適當的使用縮排(Indent),可以在定義程式區塊時讓區塊範圍看來容易分辨。
每個開發人員使用縮排的方式各不相同,您可以使用兩個空白或是四個空白,也可以按下Tab鍵來進行縮排。
良葛格的話匣子 我習慣的縮排方式是按四次空白鍵,不習慣按 Tab 鍵,因為各個文字編輯器或 IDE 對於 Tab 字元的顯示方式都不太一樣,有些文字編輯器或 IDE 預設使用 Tab 字元來自動縮排的話,我都還會將之改為預設四個空白字元進行縮排,因為空白字元顯示方式是一致的。
switch 只能比較數值或字元,不過別以為這樣它就比 if 來得沒用,使用適當的話,它可比 if 判斷式來得有效率;switch 的語法架構如下:
switch(變數名稱或運算式) {
case 符合數字或字元:
陳述句一;
break;
case 符合數字或字元:
陳述句二;
break;
default:
陳述三;
}
首先看看 switch 的括號,當中置放您要取出數值的變數,取出數值之後,程式會開始與 case 中所設定的數字或字元作比對,如果符合就執行當中的陳述句,直到遇到 break 後離開 switch 區塊,如果沒有符合的數值或字元,則會執行 default 後的陳述句,default 不一定需要,如果沒有預設要處理的動作,您可以省去這個部份。
來看看範例 3.26 的成績等級比對如何使用 switch 來改寫。
import java.util.Scanner;
public class ScoreLevel2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入分數: ");
int score = scanner.nextInt();
int level = (int) score/10;
switch(level) {
case 10:
case 9:
System.out.println("得A");
break;
case 8:
System.out.println("得B");
break;
case 7:
System.out.println("得C");
break;
case 6:
System.out.println("得D");
break;
default:
System.out.println("得E(不及格)");
}
}
}
在這個程式中,您使用除法並取得運算後的商數,如果大於 90 的話,除以 10 的商數一定是 9 或 10(100 分時),在 case 10 中沒有任何的陳述,也沒有使用 break,所以會繼續往下執行,直到遇到 break 離開 switch 為止,所以學生成績 100 分的話,也會顯示 A 的成績等級;如果比對的條件不在10到6這些值的話,會執行 default 下的陳述,這表示商數小於 6,所以學生的成績等級就顯示為 E 了。
注意在 case 後的等號是冒號而不是分號,這是個很常打錯的符號;如果您比對的是字元,則記得加上單引號(' '),例如:
case 'A':
這個程式與使用 if 來判斷成績等級的程式有何不同?如果純綷比對數字或字元的話,建議使用 switch,因為它只會在一開始的 switch 括號中取出變數值一次,然後將這個值與下面所設定的 case 比對,但如果您使用if的話,每次遇到條件式時,都要取出變數值,效率的差異就在這,例如:
if(a == 1)
// ....
else if(a == 2)
// ....
else if(a == 3)
// ....
這個程式片段在最差的狀況下,也就是 a = 3 時,共需三次比對,而每次比對都必須取出變數 a 的值一次,如果換成 switch 的話:
switch(a) {
case 1:
// ..
break;
case 2:
// ..
break;
case 3:
// ..
break;
}
在這個程式片段中,您只在一開頭 switch 的括號中取出變數 a 的值,然後逐一比對下面的 case,效率的差別就在於這邊;當然並不是使用 if 就不好,遇到複合條件時,switch 就幫不上忙了,您無法在 switch 中組合複雜的條件陳述,這時就得使用 if 了,簡單的說,if 與 switch 兩者可以搭配著靈活使用。
在 Java 中如果要進行重複性的指令執行,可以使用 for 迴圈式,它的基本語法如下:
for(初始式; 判斷式; 遞增式) {
陳述句一;
陳述句二;
}
如果陳述句只有一個,也就是非複合陳述句,{ } 可以省略不寫;for 迴圈的「第一個初始陳述句只會執行一次」,之後每次重新進行迴圈時,都會「根據判斷式來判斷是否執行下一個迴圈」,而每次執行完迴圈之後,都會「執行遞增式」。
實際看看範例 3.28 來瞭解 for 迴圈的功能。
public class SimpleLoopFor {
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
System.out.print(" " + i);
}
}
執行結果:
0 1 2 3 4 5 6 7 8 9
這是一個簡單的例子,但說明 for 的作用再適合不過,在 Java 中您可以直接在 for 中宣告變數與指定初始值,這個宣告的變數在 for 迴圈結束之後也會自動消失;初始變數的陳述句只被執行一次,接下來迴圈會根據 i 是否小於 10 來判斷是否執行迴圈,而每執行一次迴圈就將 i 加 1。
for 迴圈中也可以再使用 for 迴圈,初學者很喜歡用的例子就是顯示九九乘法表,這邊就用這個例子來說明:
public class NineTable {
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 括號中的每個陳述區塊是以分號 ';' 作區隔,而在一個陳述區塊中若想寫兩個以上的陳述句,則使用逗號 ',' 作區隔,有興趣的話,看看範例 3.30 中九九乘法表的寫法,它只使用了一個 for 迴圈就可以完成九九乘法表的列印,執行結果與範例 3.29 是一樣的。
public class NineTable2 {
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 迴圈的括號中之寫法,當然原則上並不鼓勵這麼寫,程式基本上還是以清楚易懂為原則,至於這個九九乘法表的演算其實也不難,當中的語法之前都介紹過了,您可以親自演算看看就知道怎麼回事了。
Java 提供 while 迴圈式,它根據您所指定的條件式來判斷是否執行迴圈本體,語法如下所示:
while(條件式) {
陳述句一;
陳述句二;
}
如果迴圈本體只有一個陳述句,則 while 的 { } 可以省略不寫;while 像是沒有起始陳述與終止陳述的 for 迴圈,主要用於重複性的動作,而停止條件未知何時發生的情況,例如一個使用者輸入介面,使用者可能輸入 10 次,也可能輸入 20 次,這時迴圈停止的時機是未知的,您可以使用 while 迴圈來作這個事。
一個計算輸入成績平均的程式如範例 3.31 所示。
import java.util.Scanner;
public class ScoreAverage {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int score = 0;
int sum = 0;
int count = -1;
while(score != -1) {
count++;
sum += score;
System.out.print("輸入分數(-1結束):");
score = scanner.nextInt();
}
System.out.println("平均:" + (double) sum/count);
}
}
在這個程式中,使用者的輸入次數是未知的,所以您使用 while 迴圈來判斷使用者的輸入是否為 -1,以作為迴圈執行的條件,一個執行的例子如下:
輸入分數(-1結束):99
輸入分數(-1結束):88
輸入分數(-1結束):77
輸入分數(-1結束):-1
平均:88.0
while 可以用作無窮迴圈,很多地方都用到的到無窮迴圈,例如遊戲設計中對使用者輸入裝置的輪詢(poll),或是動畫程式的播放都會使用到無窮廻圈,一個無窮迴圈如下所示:
while(true) {
迴圈內容;
....
}
無窮迴圈可以由自己迴圈中的某個條件式來結束,例如下面是一個迴圈內部終止的例子:
while(true) {
陳述句;
if(條件式)
break; // 跳離迴圈
....
}
當「條件式」成立時,會執行 break 離開 while 迴圈,這個 break 與 switch 中的作用是一樣的,都是要離開當時執行的程式區塊時使用。
while 迴圈有時稱之為「前測式迴圈」,因為它在迴圈執行前就會進行條件判斷,而另一個 do while 稱之「後測式迴圈」,它會先執行迴圈本體,然後再進行條件判斷,do while 的語法如下所示:
do {
陳述句一;
陳述句二;
....
} while(條件式);
注意 while 後面是以分號 ';'作為結束,這個很常被忽略;由於 do while 會先執行迴圈,所以它通常用於進行一些初始化或介面溝通的動作,例如範例 3.32 所示。
import java.util.Scanner;
public class OddDecider4 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int input = 0;
int replay = 0;
do {
System.out.print("輸入整數值:");
input = scanner.nextInt();
System.out.println("輸入數為奇數?" +
((input%2 == 1) ? 'Y': 'N'));
System.out.print("繼續(1:繼續 0:結束)?");
replay = scanner.nextInt();
} while(replay == 1);
}
}
執行結果:
輸入整數值:77
輸入數為奇數?Y
繼續(1:繼續 0:結束)?0
break 可以離開目前 switch、for、while、do while 的區塊,並前進至區塊後下一個陳述句,在 switch 中主要用來中斷下一個 case 的比對,在 for、while與do while 中,主要用於中斷目前的迴圈執行,break 的例子您之前已經看過不少,這邊不再舉例。
continue 的作用與 break 類似,主要使用於迴圈,所不同的是 break 會結束區塊的執行,而 continue 只會結束其之後區塊的陳述句,並跳回迴圈區塊的開頭繼續下一個迴圈,而不是離開迴圈,例如:
for(int i = 1; i < 10; i++) {
if(i == 5)
break;
System.out.println("i = " + i);
}
這段程式會顯示 i = 1 到 i = 4,因為當 i 等於 5 時就會執行 break 而離開迴圈,再看下面這個程式:
for(int i = 1; i < 10; i++) {
if(i == 5)
continue;
System.out.println("i = " + i);
}
這段程式會顯示 1 到 4,與 6 到 9,當 i 等於 5 時,會執行 continue 直接結束此次迴圈,這次迴圈中 System.out.println() 該行並沒有被執行,然後從區塊開頭執行下一次迴圈,所以 5 並沒有被顯示。
break 與 continue 還可以配合標籤使用,例如本來 break 只會離開 for 迴圈,設定標籤與區塊,則可以離開整個區塊,範例 3.33 舉個簡單的示範。
public class BreakTest {
public static void main(String[] args) {
back : {
for(int i = 0; i < 10; i++) {
if(i == 9) {
System.out.println("break");
break back;
}
}
System.out.println("test");
}
}
}
程式的執行結果會顯示 break;back 是個標籤,當 break back; 時,返回至 back 標籤處,之後整個 back 區塊不執行而跳過,所以這個程式 System.out.println("test"); 不會被執行。
事實上 continue 也有類似的用法,只不過標籤只能設定在 for 之前,範例 3.34 舉個簡單的示範。
public class ContinueTest {
public static void main(String[] args) {
back1:
for(int i = 0; i < 10; i++){
back2:
for(int j = 0; j < 10; j++) {
if(j == 9) {
continue back1;
}
}
System.out.println("test");
}
}
}
continue 配合標籤,可以自由的跳至任何一層 for 迴圈,您可以試試 continue back1 與 continue back2 的不同,設定 back1 時,System.out.println("test"); 不會被執行。