Java控制語句
目錄
- 控制語句
- 選擇結構
- if單選擇結構
- if-else雙選擇結構
- if-else if-else多選擇結構
- switch多選擇結構
- 迴圈結構
- while迴圈
- do-while迴圈
- for迴圈
- 巢狀迴圈
- break語句和continue語句
- 帶標籤的break和continue
- 語句塊
- 方法
- 方法的過載(overload)
- 遞迴結構
- 總結
控制語句
本篇文章開始我們要學習流程控制語句,流程控制語句是用來控制程式中各語句執行順序的語句,可以把語句組合成能完成一定功能的小邏輯模組。控制語句分為三類:順序、選擇和迴圈。
“順序結構”代表“先執行a,再執行b”的邏輯。比如,先找個女朋友,再給女朋友打電話;先訂婚,再結婚;
“選擇結構”代表“如果…,則…”的邏輯。比如,如果女朋友來電,則迅速接電話;如果看到紅燈,則停車;
“迴圈結構”代表“如果…,則再繼續…”的邏輯。比如,如果沒打通女朋友電話,則再繼續打一次; 如果沒找到喜歡的人,則再繼續找。
前面兩篇文章講解的程式都是順序結構,即按照書寫順序執行每一條語句,這並不是我們的重點,因此本篇文章研究的重點是“選擇結構”和“迴圈結構”。
很神奇的是,三種流程控制語句就能表示所有的事情!不信,你可以試試拆分你遇到的各種事情。實際上,任何軟體和程式,小到一個練習,大到一個作業系統,本質上都是由“變數、選擇語句、迴圈語句”組成。
這三種基本邏輯結構是相互支撐的,它們共同構成了演算法的基本結構,無論怎樣複雜的邏輯結構,都可以通過它們來表達。上述兩種結構組成的程式可以解決全部的問題,所以任何一種高階語言都具備上述兩種結構。
因此,本篇文章是大家真正跨入程式設計界的“門檻”,是成為“程式猿”的“門票”。
選擇結構
在還沒有知道Java選擇結構的時候,我們編寫的程式總是從程式入口開始,順序執行每一條語句直到執行完最後一條語句結束,但是生活中經常需要進行條件判斷,根據判斷結果決定是否做一件事情,這就需要選擇結構。
選擇結構用於判斷給定的條件,然後根據判斷的結果來控制程式的流程。
主要的選擇結構有:if選擇結構和switch多選擇結構:
-
if單選擇結構
-
if-else雙選擇結構
-
if-else if-else多選擇結構
-
switch結構
if單選擇結構
語法結構:
if(布林表示式){
語句塊
}
if語句對布林表示式進行一次判定,若判定為真,則執行{}中的語句塊,否則跳過該語句塊。
if單選擇結構流程圖:
//if單選擇結構
public class Test1 {
public static void main(String[] args) {
//通過擲三個骰子看看今天的手氣如何?
int i = (int)(6 * Math.random()) + 1;//通過Math.random()產生隨機數
int j = (int)(6 * Math.random()) + 1;
int k = (int)(6 * Math.random()) + 1;
int count = i + j + k;
//如果三個骰子之和大於15,則手氣不錯
if(count > 15) {
System.out.println("今天手氣不錯");
}
//如果三個骰子之和在10到15之間,則手氣一般
if(count >= 10 && count <= 15) { //錯誤寫法:10<=count<=15
System.out.println("今天手氣很一般");
}
//如果三個骰子之和小於10,則手氣不怎麼樣
if(count < 10) {
System.out.println("今天手氣不怎麼樣");
}
System.out.println("得了" + count + "分");
}
}
執行效果圖:
Math類的使用
1.java.lang包中的Math類提供了一些用於數學計算的方法。
2.Math.random()該方法用於產生一個0到1區間的double型別的隨機數,但是不包括1。
int i = (int) (6 * Math.random()); //產生:[0,5]之間的隨機整數
1.如果if語句不寫{},則只能作用於後面的第一條語句。
2.強烈建議,任何時候都寫上{},即使裡面只有一句話!
if-else雙選擇結構
語法結構:
//當布林表示式為真時,執行語句塊1,否則,執行語句塊2。也就是else部分。
if(布林表示式){
語句塊1
}else{
語句塊2
}
if-else雙選擇結構流程圖:
//if-else結構
public class Test2 {
public static void main(String[] args) {
//隨機產生一個[0.0, 4.0)區間的半徑,並根據半徑求圓的面積和周長
double r = 4 * Math.random();
//Math.pow(r, 2)求半徑r的平方
double area = Math.PI * Math.pow(r, 2);
double circle = 2 * Math.PI * r;
System.out.println("半徑為: " + r);
System.out.println("面積為: " + area);
System.out.println("周長為: " + circle);
//如果面積>=周長,則輸出"面積大於等於周長",否則,輸出周長大於面積
if(area >= circle) {
System.out.println("面積大於等於周長");
} else {
System.out.println("周長大於面積");
}
}
}
執行效果圖:
條件運算子有時候可用於代替if-else:
//使用if-else
public class Test3 {
public static void main(String[] args) {
int a=2;
int b=3;
if (a<b) {
System.out.println(a);
} else {
System.out.println(b);
}
}
}
執行效果圖:
//使用條件運算子
public class Test4 {
public static void main(String[] args) {
int a=2;
int b=3;
System.out.println((a<b)?a:b);
}
}
執行效果圖:
在Java中有一種特殊的運算叫做三元運算,它和if-else語句類似:
判斷條件 ? 表示式1 : 表示式2
三元運算通常用於對某個變數進行賦值,當判斷條件成立時,運算結果為表示式1的值,否則結果為表示式2的值。
//if - else條件判斷
int x = 0;
int y = 1;
int max;
if (x > y) {
max = x;
} else {
max = y;
}
//三元運算子
int x = 0;
int y = 1;
int max = x > y ? x : y; //1
if-else if-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部分。
if-else if-else多選擇結構流程圖:
對多個條件進行判斷,進行不同的處理。
//if-else if-else多選擇結構
public class Test5 {
public static void main(String[] args) {
int age = (int) (100 * Math.random());
System.out.print("年齡是" + age + ", 屬於");
if (age < 15) {
System.out.println("兒童, 喜歡玩!");
} else if (age < 25) {
System.out.println("青年, 要學習!");
} else if (age < 45) {
System.out.println("中年, 要工作!");
} else if (age < 65) {
System.out.println("中老年, 要補鈣!");
} else if (age < 85) {
System.out.println("老年, 多運動!");
} else {
System.out.println("老壽星, 古來稀!");
}
}
}
執行效果圖:
switch多選擇結構
語法結構:
switch (表示式) {
case 目標值1:
語句序列1;
break;
case 目標值2:
語句序列2;
break;
… … … … …
case 目標值n:
語句序列n;
break;
default:
預設語句;
break;
}
switch語句會根據表示式的值從相匹配的case標籤處開始執行,一直執行到break語句處或者是switch語句的末尾。如果表示式的值與任一case值不匹配,則進入default語句(如果存在default語句的情況)。
根據表示式值的不同可以執行許多不同的操作。switch語句中case標籤在JDK1.5之前必須是整數(byte、short、char、int、enum。long型別除外)或者列舉,不能是字串,在JDK1.7之後允許使用字串(String)。
大家要注意,當布林表示式是等值判斷的情況,可以使用if-else if-else多選擇結構或者switch結構,如果布林表示式區間判斷的情況,則只能使用if-else if-else多選擇結構。
switch多選擇結構流程圖:
//switch結構
public class Test6 {
public static void main(String[] args) {
char c = 'a';
int rand = (int) (26 * Math.random());
char c2 = (char) (c + rand);
System.out.print(c2 + ": ");
switch (c2) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
System.out.println("母音");
break;
case 'y':
case 'w':
System.out.println("半母音");
break;
default:
System.out.println("子音");
}
}
}
執行效果圖:
迴圈結構
迴圈結構分兩大類,一類是當型,一類是直到型。
當型:
當布林表示式條件為true時,反覆執行某語句,當布林表示式的值為false時才停止迴圈,比如:while與for迴圈。
直到型:
先執行某語句, 再判斷布林表示式,如果為true,再執行某語句,如此反覆,直到布林表示式條件為false時才停止迴圈,比如do-while迴圈。
while迴圈
語法結構:
while (布林表示式) {
迴圈體;
}
在迴圈剛開始時,會計算一次“布林表示式”的值,若條件為真,執行迴圈體。而對於後來每一次額外的迴圈,都會在開始前重新計算一次。while語句會反覆地進行條件判斷,直到條件不成立,while迴圈結束。
語句中應有使迴圈趨向於結束的語句,否則會出現無限迴圈–––"死"迴圈。
while流程圖:
//while迴圈結構:求1到100之間的累加和
public class Test7 {
public static void main(String[] args) {
int i = 0;
int sum = 0;
// 1+2+3+…+100=?
while (i <= 100) {
sum += i; //相當於sum = sum+i;
i++;
}
System.out.println("Sum= " + sum);
}
}
執行效果圖:
do-while迴圈
語法結構:
do {
迴圈體;
} while(布林表示式) ;
do-while迴圈結構會先執行迴圈體,然後再判斷布林表示式的值,若條件為真,執行迴圈體,當條件為假時結束迴圈。do-while迴圈的迴圈體至少執行一次。
do-while流程圖:
//do-while迴圈結構:1-100之間的累加和
public class Test8 {
public static void main(String[] args) {
int i = 0;
int sum = 0;
do {
sum += i; // sum = sum + i
i++;
} while (i <= 100); //此處的;不能省略
System.out.println("Sum= " + sum);
}
}
執行效果圖:
while與do-while的區別:
public class Test9 {
public static void main(String[] args) {
//while迴圈:先判斷再執行
int a = 0;
while (a < 0) {
System.out.println(a);
a++;
}
System.out.println("-----");
//do-while迴圈:先執行再判斷
a = 0;
do {
System.out.println(a);
a++;
} while (a < 0);
}
}
執行效果圖:
從執行效圖中可以看出do-while總是保證迴圈體至少會被執行一次!
for迴圈
語法結構:
for (初始表示式; 布林表示式; 迭代因子) {
迴圈體;
}
for迴圈語句是支援迭代的一種通用結構,是最有效、最靈活的迴圈結構,也是最常用的迴圈語句,一般用在迴圈次數已知的情況下。for迴圈在第一次反覆之前要進行初始化,即執行初始表示式;隨後,對布林表示式進行判定,若判定結果為true,則執行迴圈體,否則,終止迴圈;最後在每一次反覆的時候,進行某種形式的“步進”,即執行迭代因子。
A. 初始化部分設定迴圈變數的初值
B. 條件判斷部分為任意布林表示式
C. 迭代因子控制迴圈變數的增減
for迴圈在執行條件判斷後,先執行的迴圈體部分,再執行步進。
for迴圈流程圖:
//for迴圈
public class Test10 {
public static void main(String args[]) {
int sum = 0;
//1.求1-100之間的累加和
for (int i = 0; i <= 100; i++) {
sum += i;
}
System.out.println("Sum= " + sum);
//2.迴圈輸出9-1之間的數
for(int i=9;i>0;i--){
System.out.print(i+"、");
}
System.out.println();
//3.輸出90-1之間能被3整除的數
for(int i=90;i>0;i-=3){
System.out.print(i+"、");
}
System.out.println();
}
}
執行效果圖:
Java裡能用到逗號運算子的地方屈指可數,其中一處就是for迴圈的控制表示式。在控制表示式的初始化和步進控制部分,我們可以使用一系列由逗號分隔的表示式,而且那些表示式均會獨立執行。
逗號運算子:
public class Test11 {
public static void main(String[] args) {
for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) {
System.out.println("i= " + i + " j= " + j);
}
}
}
執行效果圖:
1. 無論在初始化還是在步進部分,語句都是順序執行的。
2. 儘管初始化部分可設定任意數量的定義,但都屬於同一型別。
3. 約定:只在for語句的控制表示式中寫入與迴圈變數初始化,條件判斷和迭代因子相關的表示式。
初始化部分、條件判斷部分和迭代因子可以為空語句,但必須以“;”分開:
無限迴圈:
public class Test12 {
public static void main(String[] args) {
for ( ; ; ) { // 無限迴圈: 相當於 while(true)
System.out.println("北京尚學堂");
}
}
}
編譯器將while(true)與for( ; ; )看作同一回事,都指的是無限迴圈。
在for語句的初始化部分宣告的變數,其作用域為整個for迴圈體,不能在迴圈外部使用該變數:
初始化變數的作用域:
巢狀迴圈
在一個迴圈語句內部再巢狀一個或多個迴圈,稱為巢狀迴圈。while、do-while與for迴圈可以任意巢狀多層,並且它們之間也可以互相巢狀,如最常見的在for迴圈中巢狀for迴圈:
//巢狀迴圈
public class Test14 {
public static void main(String args[]) {
for (int i=1; i <=5; i++) {
for(int j=1; j<=5; j++){
System.out.print(i+" ");
}
System.out.println();
}
}
}
執行效果圖:
使用巢狀迴圈實現九九乘法表:
public class Test15 {
public static void main(String args[]) {
for (int i = 1; i < 10; i++) { // i是一個乘數
for (int j = 1; j <= i; j++) { // j是另一個乘數
System.out.print(j + "*" + i + "=" + (i * j < 10 ? (" " + i * j) : i * j) + " ");
}
System.out.println();
}
}
}
執行效果圖:
break語句和continue語句
跳轉語句用於實現迴圈執行過程中程式流程的跳轉,在Java中的跳轉語句有break語句和continue語句。
在任何迴圈語句的主體部分,均可用break控制迴圈的流程。break用於強行退出迴圈,不執行迴圈中剩餘的語句。
break語句:在switch條件語句和迴圈語句中都可以使用break語句。當它出現在switch條件語句中時,作用是終止某個case並跳出switch結構。當它出現在迴圈語句中,作用是跳出迴圈語句,執行後面的程式碼。
public class Test16 {
public static void main(String[] args) {
int total = 0; //定義計數器
System.out.println("Begin");
while (true) {
total++; //每迴圈一次計數器加1
int i = (int) Math.round(100 * Math.random());
//當i等於88時,退出迴圈
if (i == 88) {
break;
}
}
//輸出迴圈的次數
System.out.println("Game over, used " + total + " times.");
}
}
執行效果圖:
continue 語句用在迴圈語句體中,用於終止某次迴圈過程,即跳過迴圈體中尚未執行的語句,接著進行下一次是否執行迴圈的判定。
1. continue用在while,do-while中,continue 語句立刻跳到迴圈首部,越過了當前迴圈的其餘部分。
2. continue用在for迴圈中,跳到for迴圈的迭代因子部分。
//continue語句:把100~150之間不能被3整除的數輸出,並且每行輸出5個
public class Test17 {
public static void main(String[] args) {
int count = 0; //定義計數器
for (int i = 100; i < 150; i++) {
//如果是3的倍數,則跳過本次迴圈,繼續進行下一次迴圈
if (i % 3 == 0){
continue;
}
//否則(不是3的倍數),輸出該數
System.out.print(i + "、");
count++; //沒輸出一個數,計數器加1
//根據計數器判斷每行是否已經輸出了5個數
if (count % 5 == 0) {
System.out.println();
}
}
}
}
執行效果圖:
帶標籤的break和continue
goto關鍵字很早就在程式設計語言中出現。儘管goto仍是Java的一個保留字,但並未在Java語言中得到正式使用;Java沒有goto語句。然而,在break和continue這兩個關鍵字的身上,我們仍然能看出一些goto的影子---帶標籤的break和continue。
“標籤”是指後面跟一個冒號的識別符號,例如:“label:”。對Java來說唯一用到標籤的地方是在迴圈語句之前。而在迴圈之前設定標籤的唯一理由是:我們希望在其中巢狀另一個迴圈,由於break和continue關鍵字通常只中斷當前迴圈,但若隨同標籤使用,它們就會中斷到存在標籤的地方。
在 “goto有害”論中,最有問題的就是標籤,而非goto, 隨著標籤在一個程式裡數量的增多,產生錯誤的機會也越來越多。 但Java標籤不會造成這方面的問題,因為它們的活動場所已被限死,不可通過特別的方式到處傳遞程式的控制權。由此也引出了一個有趣的問題:通過限制語句的能力,反而能使一項語言特性更加有用。
//帶標籤break和continue:控制巢狀迴圈跳轉(列印101-150之間所有的質數)
public class Test18 {
public static void main(String args[]) {
outer: for (int i = 101; i < 150; i++) {
for (int j = 2; j < i / 2; j++) {
if (i % j == 0){
continue outer;
}
}
System.out.print(i + " ");
}
}
}
執行效果圖:
語句塊
語句塊(有時叫做複合語句),是用花括號擴起的任意數量的簡單Java語句。塊確定了局部變數的作用域。塊中的程式程式碼,作為一個整體,是要被一起執行的。塊可以被巢狀在另一個塊中,但是不能在兩個巢狀的塊內宣告同名的變數。語句塊可以使用外部的變數,而外部不能使用語句塊中定義的變數,因為語句塊中定義的變數作用域只限於語句塊。
//語句塊
public class Test19 {
public static void main(String[] args) {
int n;
int a;
{
int k;
int n; //編譯錯誤:不能重複定義變數n
} //變數k的作用域到此為止
}
}
方法
方法就是一段用來完成特定功能的程式碼片段,類似於其它語言的函式。
方法用於定義該類或該類的例項的行為特徵和功能實現。 方法是類和物件行為特徵的抽象。方法很類似於面向過程中的函式。面向過程中,函式是最基本單位,整個程式由一個個函式呼叫組成。面向物件中,整個程式的基本單位是類,方法是從屬於類和物件的。
方法宣告格式:
[修飾符1 修飾符2 …] 返回值型別 方法名(形式引數列表) {
Java語句;
… … …
return 返回值;
}
方法的呼叫方式:
物件名.方法名(實參列表)
方法的詳細說明:
1. 形式引數:在方法宣告時用於接收外界傳入的資料,如果方法不需要接收任何引數,則引數列表為空,即()內不寫任何內容。格式:(引數型別 實參1,引數型別 實參2,……)。
2. 實參:呼叫方法時實際傳給方法的資料。引數型別:用於限定呼叫方法時傳入引數的資料型別。
3. 返回值:方法在執行完畢後被return語句返還給呼叫它的環境的資料。
4. 返回值型別:事先約定的返回值的資料型別,如無返回值,必須顯示指定為為void,方法中return語句可以省略。 return關鍵字:用於結束方法以及返回方法指定型別的值。
5. 修飾符:方法的修飾符比較多,有對訪問許可權進行限定的,有靜態修飾符static,還有最終修飾符final等。
方法的宣告及呼叫:
public class Test20 {
/** main方法:程式的入口 */
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
//呼叫求和的方法:將num1與num2的值傳給add方法中的n1與n2
// 求完和後將結果返回,用sum接收結果
int sum = add(num1, num2);
System.out.println("sum = " + sum); //輸出:sum = 30
//呼叫列印的方法:該方法沒有返回值
print();
}
/** 求和的方法 */
public static int add(int n1, int n2) {
int sum = n1 + n2;
return sum; //使用return返回計算的結果
}
/** 列印的方法 */
public static void print() {
System.out.println("北京歡迎你...");
}
}
執行效果圖:
//列印三個長寬不同的矩形。
public class Example19 {
public static void main(String[] args) {
//下面的迴圈是使用*列印一個寬為5、高為3的矩形
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 5; j++) {
System.out.print("*");
}
System.out.print("\n");
}
System.out.print("\n");
//下面的迴圈是使用*列印一個寬為4、高為2的矩形
for(int i = 0; i < 2; i++) {
for(int j = 0; j < 4; j++) {
System.out.print("*");
}
System.out.print("\n");
}
System.out.print("\n");
//下面的迴圈是使用*列印一個寬為10、高為6的矩形
for(int i = 0; i < 6; i++) {
for(int j = 0; j < 10; j++) {
System.out.print("*");
}
System.out.print("\n");
}
System.out.print("\n");
}
}
//將使用“*”列印矩形的功能定義為方法,在程式中呼叫三次。
public class Example20 {
public static void main(String[] args) {
printRectangle(3, 5); //呼叫printRectangle()方法實現列印矩形
printRectangle(2, 4);
printRectangle(6, 10);
}
public static void printRectangle(int height, int width) {
//下面使用巢狀for迴圈實現*列印矩形
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++) {
System.out.print("*");
}
System.out.print("\n");
}
System.out.print("\n");
}
}
public class Example21{
public static void main(String[] args) {
int area = getArea(3, 5); //呼叫getArea方法
System.out.println(" The area is " + area);
}
//下面定義了一個矩形面積的方法,接收兩個引數,其中x為高,y為寬
private static int getArea(int x, int y) {
int temp = x * y; //試一下變數temp記住運算結果
return temp; //將變數temp的值返回
}
}
1. 實參的數目、資料型別和次序必須和所呼叫的方法宣告的形式引數列表匹配。
2. return 語句終止方法的執行並指定要返回的資料。
3. Java中進行方法呼叫中傳遞引數時,遵循值傳遞的原則(傳遞的都是資料的副本):
4. 基本型別傳遞的是該資料值的copy值。
5. 引用型別傳遞的是該物件引用的copy值,但指向的是同一個物件。
方法的過載(overload)
方法的過載是指一個類中可以定義多個方法名相同,但引數型別或個數不同的方法。 呼叫時,會根據不同的引數自動匹配對應的方法。
過載的方法,實際是完全不同的方法,只是名稱相同而已!
構成方法過載的條件:
1.不同的含義:形參型別、形參個數、形參順序不同
2.只有返回值不同不構成方法的過載
int a(String str){} 與 void a(String str){} //不構成方法過載
3.只有形參的名稱不同,不構成方法的過載
int a(String str){} 與 int a(String s){} //不構成方法過載
方法過載:
public class Test21 {
public static void main(String[] args) {
System.out.println(add(3, 5)); // 8
System.out.println(add(3, 5, 10)); // 18
System.out.println(add(3.0, 5)); // 8.0
System.out.println(add(3, 5.0)); // 8.0
// 我們已經見過的方法的過載
System.out.println(); // 0個引數
System.out.println(1); // 引數是1個int
System.out.println(3.0); // 引數是1個double
}
/** 求和的方法 */
public static int add(int n1, int n2) {
int sum = n1 + n2;
return sum;
}
// 方法名相同,引數個數不同,構成過載
public static int add(int n1, int n2, int n3) {
int sum = n1 + n2 + n3;
return sum;
}
// 方法名相同,引數型別不同,構成過載
public static double add(double n1, int n2) {
double sum = n1 + n2;
return sum;
}
// 方法名相同,引數順序不同,構成過載
public static double add(int n1, double n2) {
double sum = n1 + n2;
return sum;
}
//編譯錯誤:只有返回值不同,不構成方法的過載
public static double add(int n1, int n2) {
double sum = n1 + n2;
return sum;
}
//編譯錯誤:只有引數名稱不同,不構成方法的過載
public static int add(int n2, int n1) {
double sum = n1 + n2;
return sum;
}
}
遞迴結構
遞迴是一種常見的解決問題的方法,即把問題逐漸簡單化。遞迴的基本思想就是“自己呼叫自己”,一個使用遞迴技術的方法將會直接或者間接的呼叫自己。
利用遞迴可以用簡單的程式來解決一些複雜的問題。比如:斐波那契數列的計算、漢諾塔、快排等問題。
遞迴結構包括兩個部分:
1.定義遞迴頭。解答:什麼時候不呼叫自身方法。如果沒有頭,將陷入死迴圈,也就是遞迴的結束條件。
2.遞迴體。解答:什麼時候需要呼叫自身方法。
//遞迴:計算n!
public class Test22 {
public static void main(String[] args) {
long d1 = System.currentTimeMillis();
System.out.printf("%d階乘的結果:%s%n", 10, factorial(10));
long d2 = System.currentTimeMillis();
System.out.printf("遞迴費時:%s%n", d2-d1); //耗時:32ms
}
/** 求階乘的方法*/
static long factorial(int n){
if(n==1){ //遞迴頭
return 1;
}else{ //遞迴體
return n*factorial(n-1);//n! = n * (n-1)!
}
}
}
執行效果圖:
遞迴原理分析圖:
public class Example24{
public static void main(String[] args) {
int sum = getSum(4); //呼叫遞迴方法,獲得1~4的和
System.out.println("sum = " + sum);
}
//使用遞迴實現求1~n的和
private static int getSum(int n) {
if (n == 1) {
//滿足條件,遞迴結束
return 1;
}
int temp = getSum(n - 1);
return temp + n;
}
}
執行效果圖:
遞迴原理分析圖:
遞迴的缺陷:
簡單的程式是遞迴的優點之一。但是遞迴呼叫會佔用大量的系統堆疊,記憶體耗用多,在遞迴呼叫層次多時速度要比迴圈慢的多,所以在使用遞迴時要慎重。
比如上面的遞迴耗時558ms。但是用普通迴圈的話快得多。
//使用迴圈求n!
public class Test23 {
public static void main(String[] args) {
long d3 = System.currentTimeMillis();
int a = 10;
int result = 1;
while (a > 1) {
result *= a * (a - 1);
a -= 2;
}
long d4 = System.currentTimeMillis();
System.out.println(result);
System.out.printf("普通迴圈費時:%s%n", d4 - d3);
}
}
執行效果圖:
任何能用遞迴解決的問題也能使用迭代解決。當遞迴方法可以更加自然地反映問題,並且易於理解和除錯,並且不強調效率問題時,可以採用遞迴;
在要求高效能的情況下儘量避免使用遞迴,遞迴呼叫既花時間又耗記憶體。
總結
1.從結構化程式設計角度出發,程式有三種結構:順序結構、選擇結構和迴圈結構。
2.選擇結構
(1)if單選擇結構 if-else雙選擇結構 if-else if-else多選擇結構。
(2)switch多選擇結構。
3.多選擇結構與switch的關係:當布林表示式是等值判斷的情況,可使用多重選擇結構或switch結構,如果布林表示式區間判斷的情況,則只能使用多重選擇結構。
(1)迴圈結構
(2)當型:while與for
(3)直到型:do-while
4.while與do-while的區別,在布林表示式的值為false時while的迴圈體一次也不執行,而do-while至少執行一次。
5.break可以在switch與迴圈結構中使用,而continue只能在迴圈結構中使用。
6.方法就是一段用來完成特定功能的程式碼片段,類似於其它語言的函式。
7.方法的過載是指一個類中可以定義多個方法名相同,但引數不同的方法。 呼叫時,會根據不同的引數自動匹配對應的方法。
8.任何能用遞迴解決的問題也能使用迭代解決。在要求高效能的情況下儘量避免使用遞迴,遞迴呼叫既花時間又耗記憶體。
轉載自http://www.sxt.cn/Java_jQuery_in_action/openketang-Summery.html