java基礎知識總結(四)——控制語句、方法、以及遞迴
條件結構
1、if單分支結構
語法結構:
if(布林表示式){
語句塊
}
if語句對布林表示式進行一次判定,若判定為真,則執行{}中的語句塊,否則跳過該語句塊。流程圖如下圖所示。
注意:如果if語句不寫{},則只能作用於後面的第一條語句。
2、if-else雙分支結構
語法結構:
if(布林表示式){
語句塊1
}else{
語句塊2
}
當布林表示式為真時,執行語句塊1,否則,執行語句塊2。也就是else部分。流程圖如下如所示。
Tip:條件運算子有時候可用於代替if-else
3、if-elseif-else多分支結構
語法結構:
if(布林表示式1){
語句塊1;
}else if(布林表示式2){
語句塊2;
}......
else if(布林表示式n){
語句塊n;
}else{
語句塊n+1;
}
當布林表示式1為真時,執行語句塊1;否則,判斷布林表示式2,當布林表示式2為真時,執行語句塊2;否則,繼續判斷布林表示式3······;如果1~n個布林表示式均判定為假時,則執行語句塊n+1,也就是else部分。流程圖如下圖所示。
4、switch語句
語法結構:
switch(表示式){
case值1:
語句序列1;
[break];
case值2:
語句序列2;
[break];
...............
[default:
預設語句;]
}
switch語句會根據表示式的值從相匹配的case標籤處開始執行,一直執行到break語句處或者是switch語句的末尾。如果表示式的值與任一case值不匹配,則進入default語句(如果存在default語句的情況)。
根據表示式值的不同可以執行許多不同的操作。switch語句中case標籤在JDK1.5之前必須是整數(long型別除外)或者列舉,不能是字串,在JDK1.7之後允許使用字串(String)。
switch多分支結構的流程圖如下圖所示。
迴圈結構
迴圈結構分兩大類,一類是當型,一類是直到型。
當型:
當布林表示式條件為true時,反覆執行某語句,當布林表示式的值為false時才停止迴圈,比如:while與for迴圈。
直到型:
先執行某語句,再判斷布林表示式,如果為true,再執行某語句,如此反覆,直到布林表示式條件為false時才停止迴圈,比如do-while迴圈。
1、while迴圈
語法結構:
while(布林表示式){
迴圈體;
}
在迴圈剛開始時,會計算一次“布林表示式”的值,若條件為真,執行迴圈體。而對於後來每一次額外的迴圈,都會在開始前重新計算一次。 語句中應有使迴圈趨向於結束的語句,否則會出現無限迴圈–––"死"迴圈。while迴圈結構流程圖如下圖所示。2、do-while迴圈
語法結構:
do{
迴圈體;
}while(布林表示式);
do-while迴圈結構會先執行迴圈體,然後再判斷布林表示式的值,若條件為真,執行迴圈體,當條件為假時結束迴圈。do-while迴圈的迴圈體至少執行一次。do-while迴圈結構流程圖如下圖所示。
Tip:while與do-while的區別在於,while迴圈中的迴圈體可能一次也不執行,而do-while迴圈中的迴圈體至少執行一次。
3、for迴圈
語法結構:
for(初始表示式;布林表示式;迭代因子){
迴圈體;
}
for迴圈語句是支援迭代的一種通用結構,是最有效、最靈活的迴圈結構。for迴圈在第一次反覆之前要進行初始化,即執行初始表示式;隨後,對布林表示式進行判定,若判定結果為true,則執行迴圈體,否則,終止迴圈;最後在每一次反覆的時候,進行某種形式的“步進”,即執行迭代因子。
初始化部分設定迴圈變數的初值。
條件判斷部分為任意布林表示式。
迭代因子控制迴圈變數的增減for迴圈在執行條件判定後,先執行的迴圈體部分,再執行步進。
for迴圈結構的流程圖如下圖所示。
注意:
1、無論在初始化還是在步進部分,語句都是順序執行的。
2、儘管初始化部分可設定任意數量的定義,但都屬於同一型別。
3、約定:只在for語句的控制表示式中寫入與迴圈變數初始化,條件判斷和迭代因子相關的表示式。
4、初始化部分、條件判斷部分和迭代因子可以為空語句,但必須以“;”分開。
5、編譯器將while(true)與for(;;)看作同一回事,都指的是無限迴圈。在for語句的初始化部分宣告的變數,其作用域為整個for迴圈體,不能在迴圈外部使用該變數。
break語句和continue語句
在任何迴圈語句的主體部分,均可用break控制迴圈的流程。break用於強行退出迴圈,不執行迴圈中剩餘的語句。
continue語句用在迴圈語句體中,用於終止某次迴圈過程,即跳過迴圈體中尚未執行的語句,接著進行下一次是否執行迴圈的判定。
注意:
1、continue用在while,do-while中,continue語句立刻跳到迴圈首部,越過了當前迴圈的其餘部分。
2、continue用在for迴圈中,跳到for迴圈的迭代因子部分。
帶標籤的break語句和continue語句
goto關鍵字很早就在程式設計語言中出現。儘管goto仍是Java的一個保留字,但並未在Java語言中得到正式使用;Java沒有goto語句。然而,在break和continue這兩個關鍵字的身上,我們仍然能看出一些goto的影子---帶標籤的break和continue。
“標籤”是指後面跟一個冒號的識別符號,例如:“label:”。對Java來說唯一用到標籤的地方是在迴圈語句之前。而在迴圈之前設定標籤的唯一理由是:我們希望在其中巢狀另一個迴圈,由於break和continue關鍵字通常只中斷當前迴圈,但若隨同標籤使用,它們就會中斷到存在標籤的地方。
在“goto有害”論中,最有問題的就是標籤,而非goto,隨著標籤在一個程式裡數量的增多,產生錯誤的機會也越來越多。但Java標籤不會造成這方面的問題,因為它們的活動場所已被限死,不可通過特別的方式到處傳遞程式的控制權。由此也引出了一個有趣的問題:通過限制語句的能力,反而能使一項語言特性更加有用。
1 //控制巢狀迴圈跳轉(列印101-150之間所有的質數) 2 public class Test18{ 3 public static void main(String args[]){ 4 outer:for(int i=101;i<150;i++){ 5 for(int j=2;j<i/2;j++){ 6 if(i%j==0){ 7 continue outer; 8 } 9 } 10 System.out.print(i+""); 11 } 12 } 13 }
執行結果:
方法
方法(method)就是一段用來完成特定功能的程式碼片段,類似於其它語言的函式(function)。方法用於定義該類或該類的例項的行為特徵和功能實現。方法是類和物件行為特徵的抽象。方法很類似於面向過程中的函式。面向過程中,函式是最基本單位,整個程式由一個個函式呼叫組成。面向物件中,整個程式的基本單位是類,方法是從屬於類和物件的。
方法宣告格式:
[修飾符1 修飾符2...] 返回值型別 方法名(形式引數列表){
Java語句;
.........
}
方法的呼叫方式:
物件名.方法名(實參列表)
方法的詳細說明:
形式引數:在方法宣告時用於接收外界傳入的資料。
實參:呼叫方法時實際傳給方法的資料。
返回值:方法在執行完畢後返還給呼叫它的環境的資料。
返回值型別:事先約定的返回值的資料型別,如無返回值,必須指定為void。
注意:
1、實參的數目、資料型別和次序必須和所呼叫的方法宣告的形式引數列表匹配。
2、return語句終止方法的執行並指定要返回的資料。
3、Java中進行方法呼叫中傳遞引數時,遵循值傳遞的原則(傳遞的都是資料的副本):基本型別傳遞的是該資料值的copy值。引用型別傳遞的是該物件引用的copy值,但指向的是同一個物件。
方法的過載(overload)
方法的過載是指一個類中可以定義多個方法名相同,但引數不同的方法。呼叫時,會根據不同的引數自動匹配對應的方法。
Tip:過載的方法,實際是完全不同的方法,只是名稱相同而已!
構成方法過載的條件:
1、不同的含義:形參型別、形參個數、形參順序不同。
2、只有返回值不同不構成方法的過載如:inta(Stringstr){}與voida(Stringstr){}不構成方法過載。
3、只有形參的名稱不同,不構成方法的過載如:inta(Stringstr){}與inta(Strings){}不構成方法過載。
遞迴結構
遞迴是一種常見的解決問題的方法,即把問題逐漸簡單化。遞迴的基本思想就是“自己呼叫自己”,一個使用遞迴技術的方法將會直接或者間接的呼叫自己。
利用遞迴可以用簡單的程式來解決一些複雜的問題。比如:斐波那契數列的計算、漢諾塔、快排等問題。
遞迴結構包括兩個部分:
定義遞迴頭:什麼時候不呼叫自身方法。如果沒有頭,將陷入死迴圈,也就是遞迴的結束條件。
遞迴體:什麼時候需要呼叫自身方法。
1 //使用遞迴求n! 2 public class Test22{ 3 public static void main(String[] args){ 4 long d1=System.currentTimeMillis(); 5 System.out.printf("%d階乘的結果:%s%n",10,factorial(10)); 6 long d2=System.currentTimeMillis(); 7 System.out.printf("遞迴費時:%s%n",d2-d1);//耗時:32ms 8 } 9 10 /* 11 *求階乘的方法 12 */ 13 static long factorial(int n){ 14 if(n==1){ 15 //遞迴頭 16 return1; 17 }else{ 18 //遞迴體 19 return n*factorial(n-1);//n!=n*(n-1)! 20 } 21 } 22 } 23
執行結果:
遞迴的缺陷
簡單的程式是遞迴的優點之一。但是遞迴呼叫會佔用大量的系統堆疊,記憶體耗用多,在遞迴呼叫層次多時速度要比迴圈慢的多,所以在使用遞迴時要慎重。
注意:
1、任何能用遞迴解決的問題也能使用迭代解決。當遞迴方法可以更加自然地反映問題,並且易於理解和除錯,並且不強調效率問題時,可以採用遞迴。
2、在要求高效能的情況下儘量避免使用遞迴,遞迴呼叫既花時間又耗記憶體。