JAVA的基本結構就是順序結構,除非特別指明,否則就按照順序一句一句執行。
順序結構是最簡單的演算法結構。
語句與語句之間,框與框之間都是按從上到下的順序進行的,它是有若幹個依次執行的處理步驟組成的,它是任何一個演算法都離不開的一種基本演算法結構。
Java 支援兩種選擇語句:if 語句和 switch 語句。
其中 if 語句使用布爾表達式或布爾值作爲分支條件來進行分支控制,而 switch 語句則用於對多個整型值進行匹配,從而實現分支控制。這些語句允許你只有在程式執行時才能 纔能知道其狀態的情況下,控製程式的執行過程。
選擇結構(也叫分支結構)解決了順序結構不能判斷的缺點,可以根據一個條件判斷執行哪些語句塊。選擇結構適合於帶有邏輯或關係比較等條件判斷的計算。例如,判斷是否到下班時間,判斷兩個數的大小等。
if 語句是使用最多的條件分支結構,它屬於選擇語句,也可以稱爲條件語句。
if 選擇結構是根據條件判斷之後再做處理的一種語法結構。預設情況下,if 語句控制着下方緊跟的一條語句的執行。不過,通過語句塊,if 語句可以控制多個語句。
if 語句的最簡語法格式如下,表示「如果滿足某種條件,就進行某種處理」。
if(布爾表達式) {
//if 語句中的程式碼塊。
}
//if 語句塊後面的程式碼。
其中「條件表達式」和「語句塊」是比較重要的兩個地方。
if 條件語句的執行流程如圖 1 所示。
編寫一個 Java 程式,允許使用者從鍵盤輸入一個數字,再判斷該數是否大於 100。使用 if 語句的實現程式碼如下:
public static void main(String[] args) {
System.out.println("請輸入一個數字:");
Scanner input = new Scanner(System.in);
int num = input.nextInt(); // 接收鍵盤輸入數據
// 判斷使用者輸入的數據是否大於100
if (num > 100) {
System.out.println("輸入的數位大於100");
}
// 判斷使用者輸入的數據是否等於100
if (num == 100) {
System.out.println("輸入的數位等於100");
}
// 判斷使用者輸入的數據是否小於100
if (num < 100) {
System.out.println("輸入的數位小於100");
}
}
執行該程式,分別使用鍵盤輸入 99、100 和 105,結果如下所示:
請輸入一個數字:
99
輸入的數位小於100
請輸入一個數字:
100
輸入的數位等於100
請輸入一個數字:
105
輸入的數位大於100
單 if 語句僅能在滿足條件時使用,而無法執行任何其他操作(停止)。而結合 else 語句的 if 可以定義兩個操作,此時的 if…else 語句表示「如果條件正確則執行一個操作,否則執行另一個操作」。
if(布爾表達式){
//如果布爾表達式的值爲true
}else{
//如果布爾表達式的值爲false
}
//if...else 語句塊後面的程式碼。
在上述語法格式中,如果 if 關鍵字後面的表達式成立,那麼就執行語句塊 1,否則的話則執行語句塊 2,其執行流程如圖 2 所示。
if 語句的主要功能是給程式提供一個分支。然而,有時候程式中僅僅多一個分支是遠遠不夠的,甚至有時候程式的分支會很複雜,這就需要使用多分支的 if…else if 語句。
通常表現爲「如果滿足某種條件,就進行某種處理,否則如果滿足另一種條件才執行另一種處理……,這些條件都不滿足則執行最後一種條件」。
if…else if 多分支語句的語法格式如下所示:
if(布爾表達式 1){
//如果布爾表達式 1的值爲true執行程式碼
}else if(布爾表達式 2){
//如果布爾表達式 2的值爲true執行程式碼
}else if(布爾表達式 3){
//如果布爾表達式 3的值爲true執行程式碼
}else {
//如果以上布爾表達式都不爲true執行程式碼
}
可以看出,else-if 結構實際上是 if-else 結構的多層巢狀。明顯的特點就是在多個分支中只執行一個語句組,而其他分支都不執行,所以這種結構可以用於有多種判斷結果的分支中。
在使用 if…else if 語句時,依次判斷表達式的值,當某個分支的條件表達式的值爲 true 時,則執行該分支對應的語句塊,然後跳到整個 if 語句之外繼續執行程式。如果所有的表達式均爲 false,則執行語句塊 n+1,然後繼續執行後續程式,其執行流程如圖所示。
if 語句的用法非常靈活,不僅可以單獨使用,還可以在 if 語句裡巢狀另一個 if 語句。同樣,if…else 語句和 if…else if 語句中也可以巢狀另一個 if 結構的語句,以完成更深層次的判斷。
if(布爾表達式 1){
//如果布爾表達式 1的值爲true執行程式碼
if(布爾表達式 2){
//如果布爾表達式 2的值爲true執行程式碼
}
}
在上述格式中,應該注意每一條 else 與離它最近且沒有其他 else 對應的 if 相搭配,其執行流程如圖 所示。
if…else 語句可以用來描述一個「二岔路口」,我們只能選擇其中一條路來繼續走,然而生活中經常會碰到「多岔路口」的情況。
switch 語句提供了 if 語句的一個變通形式,可以從多個語句塊中選擇其中的一個執行。
switch 語句是 Java 的多路分支語句。它提供了一種基於一個表達式的值來使程式執行不同部分的簡單方法。因此,它提供了一個比一系列 if-else-if 語句更好的選擇。
//你可以有任意數量的case語句
switch(expression){
case value :
//語句
break; //可選
case value :
//語句
break; //可選
default : //可選
//語句
}
switch 語句的執行過程如下:表達式的值與每個 case 語句中的常數作比較。如果發現了一個與之相匹配的,則執行該 case 語句後的程式碼。如果沒有一個 case 常數與表達式的值相匹配,則執行 default 語句。當然,default 語句是可選的。如果沒有相匹配的 case 語句,也沒有 default 語句,則什麼也不執行。
if 和 switch 語句都表示條件語句,可以從使用效率和實用性兩方面加以區分。
從使用效率上區分,在對同一個變數的不同值作條件判斷時,既可以使用 switch 語句,也可以使用 if 語句。使用 switch 語句的效率更高一些,尤其是判斷的分支越多,越明顯。
從語句的實用性角度區分,switch 語句不如 if 條件語句,if 語句是應用最廣泛和最實用的語句。
在程式開發的過程中,何時使用 if 語句和 switch 語句,需要根據實際情況而定,應儘量做到物盡其用。不能因爲 switch 語句的效率高就一直使用,也不能因爲 if 語句常用就不用 switch 語句。需要根據實際情況,具體問題具體分析,使用最適合的條件語句。
回圈是程式中的重要流程結構之一。回圈語句能夠使程式程式碼重複執行,適用於需要重複一段程式碼直到滿足特定條件爲止的情況。
所有流行的程式語言中都有回圈語句。Java 中採用的回圈語句與C語言中的回圈語句相似,主要有 while、do-while 和 for。另外 Java 5 之後推出了 for-each 回圈語句,for-each 回圈是 for 回圈的變形,它是專門爲集合遍歷而設計的。for-each 並不是一個關鍵字。
回圈語句可以在滿足回圈條件的情況下,反覆 反復執行某一段程式碼,這段被重複執行的程式碼被稱爲回圈體。當反覆 反復執行這個回圈體時,需要在合適的時候把回圈條件改爲假,從而結束回圈,否則回圈將一直執行下去,形成死回圈。
回圈語句可能包含如下 4 個部分。
while 語句是 Java 最基本的回圈語句,是一種先判斷的回圈結構,可以在一定條件下重複執行一段程式碼。該語句需要判斷一個測試條件,如果該條件爲真,則執行回圈語句(回圈語句可以是一條或多條),否則跳出回圈。
while 回圈語句的語法結構如下:
//**注意:我們大多數情況是會讓回圈停止下來的,我們需要一個讓表達式失效的方式來結束回圈。**
while( 布爾表達式 ) {
//回圈內容
}
其中語句塊中的程式碼可以是一條或者多條語句,而條件表達式是一個有效的 boolean 表達式,它決定了是否執行回圈體。當條件表達式的值爲 true 時,就執行大括號中的語句塊。
執行完畢,再次檢查表達式是否爲 true,如果還爲 true,則再次執行大括號中的程式碼,否則就跳出回圈,執行 while 回圈之後的程式碼。圖 1 表示了 while 回圈語句的執行流程。
如果 while 回圈一開始條件表達式就是假的,那麼回圈體就根本不被執行。然而,有時需要在開始時條件表達式即使是假的情況下,while 回圈至少也要執行一次。換句話說,有時你需要在一次回圈結束後再測試中止表達式,而不是在回圈開始時。
幸運的是,Java就提供了這樣的回圈:do-while回圈。do-while 回圈語句也是 Java 中運用廣泛的回圈語句,它由回圈條件和回圈體組成,但它與 while 語句略有不同。do-while 回圈語句的特點是先執行回圈體,然後判斷回圈條件是否成立。
do-while 語句的語法格式如下:
//注意:布爾表達式在回圈體的後面,所以語句塊在檢測布爾表達式之前已經執行了。
//如果布爾表達式的值爲true,則語句塊一直執行,直到布爾表達式的值爲 false。
do {
//程式碼語句
}while(布爾表達式);
以上語句的執行過程是,首先執行一次回圈操作,然後再判斷 while 後面的條件表達式是否爲 true,如果回圈條件滿足,回圈繼續執行,否則退出回圈。while 語句後必須以分號表示回圈結束,其執行流程如圖 2 所示。
for 語句是應用最廣泛、功能最強的一種回圈語句。大部分情況下,for 回圈可以代替 while 回圈、do while 回圈。
for 語句是一種在程式執行前就要先判斷條件表達式是否爲真的回圈語句。假如條件表達式的結果爲假,那麼它的回圈語句根本不會執行。for 語句通常使用在知道回圈次數的回圈中。
for 語句語法格式如下所示。
for(賦值語句; 條件語句; 迭代語句,通常使用 ++ 或 -- 運算子) {
//程式碼語句
}
for 關鍵字後面括號中的 3 個條件表達式必須用「;」隔開。for 回圈中的這 3 部分以及大括號中使回圈體必需的 4 個組成部分完美地結合在一起,簡單明瞭。
for 回圈語句執行的過程爲:首先執行條件表達式 1 進行初始化,然後判斷條件表達式 2 的值是否爲 true,如果爲 true,則執行回圈體語句塊;否則直接退出回圈。最後執行表達式 3,改變回圈變數的值,至此完成一次回圈。接下來進行下一次回圈,直到條件表達式 2 的值爲 false,才結束回圈,其執行流程如圖 1 所示。
值得指出的是,for 回圈的回圈迭代語句並沒有與回圈體放在一起,因此即使在執行回圈體時遇到 continue 語句結束本次回圈,回圈迭代語句也一樣會得到執行。
for 回圈和 while、do while 回圈不一樣:由於 while、do while 回圈的回圈迭代語句緊跟着回圈體,因此如果回圈體不能完全執行,如使用 continue 語句來結束本次回圈,則回圈迭代語句不會被執行。但 for 回圈的回圈迭代語句並沒有與回圈體放在一起,因此不管是否使用 continue 語句來結束本次回圈,回圈迭代語句一樣會獲得執行。
與前面回圈類似的是,如果回圈體只有一行語句,那麼回圈體的大括號可以省略。
demo for回圈 九九乘法表,例子:
for (int i = 1; i <= 9; i++) {
for (int i1=1; i1 <= i; i1++) {
System.out.print(i1 + " * " + i + " = " + i*i1 + "\t");
}
System.out.println();
}
結果
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
JDK 1.5 引進了一種新的回圈型別,被稱爲 For-Each 回圈或者加強型回圈,能在不使用下標的情況下遍歷陣列。
foreach 回圈語句是 Java 1.5 的新特徵之一,在遍歷陣列、集合方面,foreach 爲開發者提供了極大的方便。foreach 回圈語句是 for 語句的特殊簡化版本,主要用於執行遍歷功能的回圈。
foreach 回圈語句的語法格式如下:
for(宣告語句 : 表達式) {
//程式碼句子
}
for(type element: array){
System.out.println(element);
}
其中,「型別」爲集合元素的型別,「變數名」表示集閤中的每一個元素,「集合」是被遍歷的集合物件或陣列。每執行一次回圈語句,回圈變數就讀取集閤中的一個元素,其執行流程如圖 1 所示。
foreach 回圈和普通回圈不同的是,它無須回圈條件,無須回圈迭代語句,這些部分都由系統來完成,foreach 回圈自動迭代陣列的每個元素,當每個元素都被迭代一次後,foreach 回圈自動結束。
當使用 foreach 回圈來迭代輸出陣列元素或集合元素時,通常不要對回圈變數進行賦值,雖然這種賦值在語法上是允許的,但沒有太大的實際意義,而且極容易引起錯誤
當使用 foreach 來迭代存取陣列元素時,foreach 中的回圈變數相當於一個臨時變數,系統會把陣列元素依次賦給這個臨時變數,而這個臨時變數並不是陣列元素,它只是儲存了陣列元素的值。因此,如果希望改變陣列元素的值,則不能使用這種 foreach 回圈。
使用 foreach 回圈迭代陣列元素時,並不能改變陣列元素的值,因此不要對 foreach 的回圈變數進行賦值。
return 關鍵字並不是專門用於結束回圈的,return 語句用於終止函數的執行或退出類的方法,並把控制權返回該方法的呼叫者。如果這個方法帶有返回型別,return 語句就必須返回這個型別的值;如果這個方法沒有返回值,可以使用沒有表達式的 return 語句。
return 語句的一般語法格式如下:
return 與方法相同類型的變數;
如果一個方法使用了 return 語句並且後面跟有該方法返回型別的值,那麼呼叫此方法後,所得到的結果爲該方法返回的值。
某些時候需要在某種條件出現時強行終止回圈,而不是等到回圈條件爲 false 時才退出回圈。此時,可以使用 break 來完成這個功能。
break 用於完全結束一個回圈,跳出回圈體。不管是哪種回圈,一旦在回圈體中遇到 break,系統將完全結束該回圈,開始執行回圈之後的程式碼。
在 Java 中,break 語句有 3 種作用,分別是:在 switch 語句中終止一個語句序列、使用 break 語句直接強行退出回圈和使用 break 語句實現 goto 的功能。
可以使用 break 語句強行退出回圈,忽略回圈體中的任何其他語句和回圈的條件判斷。在回圈中遇到 break 語句時,回圈被終止,在回圈後面的語句重新開始。
使用 break 語句直接強行退出回圈的範例如下:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// 定義變數儲存小明的回答
String answer = "";
// 一圈100米,1000米爲10圈,即爲回圈的次數
for (int i = 0; i < 10; i++) {
System.out.println("跑的是第" + (i + 1) + "圈");
System.out.println("還能堅持嗎?"); // 獲取小明的回答
answer = input.next();
// 判斷小明的回答是否爲y?如果不是,則放棄,跳出回圈
if (!answer.equals("y")) {
System.out.println("放棄");
break;
}
// 回圈之後的程式碼
System.out.println("加油!繼續!");
}
}
該程式執行後的效果如下所示:
跑的是第1圈
還能堅持嗎?
y
加油!繼續!
跑的是第2圈
還能堅持嗎?
y
加油!繼續!
跑的是第3圈
還能堅持嗎?
n
放棄
注意:一個回圈中可以有一個以上的 break 語句,但是過多的 break 語句會破壞程式碼結構。switch 回圈語句中的 break 僅影響 switch 語句,不會影響回圈。
有時候,在巢狀很深的回圈語句中會發生一些不可預料的事情。此時可能更加希望跳到巢狀的所有回圈語句之外。通過新增一些額外的條件判斷實現各層回圈的檢測很不方便。
幸運的是,Java 與 C++ 不同,Java 提供了一種帶標籤的 break 語句,用於跳出多重巢狀的回圈語句。
break 語句可以實現 goto 的功能,並且 Java 定義了 break 語句的一種擴充套件形式來處理退出巢狀很深的回圈這個問題。
通過使用擴充套件的 break 語句,可以終止執行一個或者幾個任意程式碼塊,這些程式碼塊不必是一個回圈或一個 switch 語句的一部分。同時這種擴充套件的 break 語句帶有標籤,可以明確指定從何處重新開始執行。
break 除了具有 goto 退出深層回圈巢狀作用外,還保留了一些程式結構化的特性。
標籤 break 語句的通用格式如下:
break label;
label 是標識程式碼塊的標籤。當執行這種形式的 break 語句時,控制權被傳遞出指定的程式碼塊。被加標籤的程式碼塊必須包圍 break 語句,但是它不需要直接包圍 break 的塊。也就是說,可以使用一個加標籤的 break 語句來退出一系列的巢狀塊,但是不能使用 break 語句將控制權傳遞到不包含 break 語句的程式碼塊。
用標籤(label)可以指定一個程式碼塊,標籤可以是任何合法有效的 Java 識別符號,後跟一個冒號。加上標籤的程式碼塊可以作爲 break 語句的物件,使程式在加標籤的塊的結尾繼續執行。
帶標籤的break 語句的範例。
public class GotoDemo {
public static void main(String[] args) {
label: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 8; j++) {
System.out.println(j);
if (j % 2 != 0) {
break label;
}
}
}
}
}
以上程式的執行結果爲:
0
1
這裏的 label 是標籤的名稱,可以爲 Java 語言中任意合法的識別符號。標籤語句必須和回圈匹配使用,使用時書寫在對應的回圈語句的上面,標籤語句以冒號結束。如果需要中斷標籤語句對應的回圈,可以採用 break 後面跟標籤名的方式。
注意:通常緊跟 break 之後的標籤,必須在 break 所在回圈的外層回圈之前定義纔有意義。
有時強迫一個回圈提早反覆 反復是有用的,也就是,你可能想要繼續執行回圈,但是要忽略這次重複剩餘的回圈體的語句,所以 Java 提供了 continue 語句。continue 語句是 break 語句的補充。
與 break 語句一樣, 它將中斷正常的控制流程。continue 語句將控制轉移到最內層回圈的首部。
continue 語句是跳過回圈體中剩餘的語句而強制執行下一次回圈,其作用爲結束本次回圈,即跳過回圈體中下面 下麪尚未執行的語句,接着進行下一次是否執行回圈的判定。
continue 語句類似於 break 語句,但它只能出現在回圈體中。它與 break 語句的區別在於:continue 並不是中斷回圈語句,而是中止當前迭代的回圈,進入下一次的迭代。簡單來講,continue 是忽略回圈語句的當次回圈。
注意:continue 語句只能用在 while 語句、for 語句或者 foreach 語句的回圈體之中,在這之外的任何地方使用它都會引起語法錯誤。
在回圈體中使用 continue 語句有兩種方式可以帶有標籤,也可以不帶標籤。語法格式如下:
下面 下麪看一個範例,程式碼如下:
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int i = 0; i < numbers.length; i++) {
if (i == 3) {
continue;
}
System.out.println("Count is: " + i);
}
在上述程式程式碼中,當條件 i==3 的時候執行 continue 語句,continue 語句會終止本次回圈,回圈體中 continue 之後的語句將不再執行,接着進行下次回圈,所以輸出結果中沒有 3。程式執行結果如下:
Count is: 0
Count is: 1
Count is: 2
Count is: 4
Count is: 5
Count is: 6
Count is: 7
Count is: 8
Count is: 9
帶標籤的 continue 語句範例程式碼如下:
public static void main(String[] args) {
label1: for (int x = 0; x < 5; x++) {
for (int y = 5; y > 0; y--) {
if (y == x) {
continue label1;
}
System.out.println(x+","+y);
}
}
System.out.println("Game Over!");
}
預設情況下,continue 只會跳出最近的內回圈(程式碼第 3 行的 for 回圈),如果要跳出程式碼第 2 行的外回圈,可以爲外回圈新增一個標籤 label1,然後在第 5 行的 continue 語句後面指定這個標籤 label1,這樣當條件滿足執行 continue 語句時,程式就會跳轉出外回圈。
程式執行結果如下:
0,5
0,4
0,3
0,2
0,1
1,5
1,4
1,3
1,2
2,5
2,4
2,3
3,5
3,4
4,5
Game Over!
由於跳過了 x == y,因此下面 下麪的內容沒有輸出。
1,1
2,2
3,3
4,4
利用過 Java 語言中的流程控制語句,如條件語句、回圈語句和跳轉語句等知識輸出一個指定行數的楊輝三角形。
楊輝三角形由數位進行排列,可以把它看作是一個數字表,其基本特性是兩側數值均爲 1,其他位置的數值是其左上方數值與右上角數值之和。列印楊輝三角形時需要使用到 for 回圈語句。
列印楊輝三角形的實現思路是:
實現步驟如下:
(1) 建立名稱爲 Test28 的類,在該類中宣告 num() 方法,在 num() 方法中傳入兩個參數,即 x 和 y。其中,x 表示行,y 表示列。num() 方法用於計算第 x 行第 y 列的數值。程式碼如下:
public static int num(int x, int y) {
if (y == 1 || y == x) {
return 1;
}
int c = num(x - 1, y - 1) + num(x - 1, y);
return c;
}
(2) 建立名稱爲 calculate 的方法,在該方法中傳入一個 int 型別的參數,該參數表示列印楊輝三角形的行數。程式碼如下
public static void calculate(int row) {
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= row - i; j++) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
// 列印空格後面的字元, 從第1 列開始往後列印
System.out.print(num(i, j) + " ");
}
System.out.println();
}
}
(3) 在 main() 方法中新增程式碼,首先接收使用者在控制檯輸入的列印行數,然後將行數作爲參數傳入到呼叫的 calculate() 方法中。程式碼如下:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("列印楊輝三角形的行數:");
int row = scan.nextInt();
calculate(row);
}
(4) 執行程式碼進行測試,其執行結果如下所示:
列印楊輝三角形的行數:7
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
任何程式語言中最常見的程式結構就是順序結構。順序結構就是程式從上到下逐行的執行,中間沒有任何判斷和跳轉。
如果 main 方法的多行程式碼之間沒有任何流程控制,則程式總是從上向下依次執行,排在前面的程式碼先執行,排在後面的程式碼後執行。這意味着:如果沒有流程控制,Java 方法裡的語句是一個順序執行流,從上向下依次執行每條語句。
不論哪一種程式語言,都會提供兩種基本的流程控制結構:分支結構和回圈結構。
Java 同樣提供了這兩種流程控制結構的語法,Java 提供了 if 和 switch 兩種分支語句,並提供了 while、do while 和 for 三種回圈語句。一般寫回圈語句時,分以下三步走:
除此之外,JDK5 還提供了一種新的回圈:foreach 回圈,能以更簡單的方式來遍歷集合、陣列的元素。
Java 還提供了 break、continue 和 return 來控製程式的回圈結構,作用如下:
當在實現某個功能語句時,如果需要通過某一個條件去判斷,則用選擇結構。
當實現某個功能需要通過回圈去實現,則用回圈結構。
當然回圈和選擇是可以相互巢狀的。