源文件中的語句一般按照它們出現的順序從上到下執行,可是,控制流語句經過使用決策、循環和分支來分解執行流程,使你的程序可以有條件地執行特定的代碼塊,本節描述Java編程語言支持的決策語句(if-then
,if-then-else
,switch
),循環語句(for
,while
,do-while
)以及分支語句(break
,continue
,return
)。java
if-then
語句是全部控制流語句中最基本的語句,它告訴程序只有在特定測試評估爲true
時才執行某段代碼,例如,Bicycle
類能夠容許制動器僅在自行車已經運動時下降自行車的速度,applyBrakes
方法的一種可能實現以下:程序員
void applyBrakes() { // the "if" clause: bicycle must be moving if (isMoving){ // the "then" clause: decrease current speed currentSpeed--; } }
若是此測試評估爲false
(意味着自行車不運動),則控制跳轉到if-then
語句的末尾。express
此外,只要「then」子句只包含一個語句,開括號和結束括號是可選的:編程
void applyBrakes() { // same as above, but without braces if (isMoving) currentSpeed--; }
決定什麼時候省略括號是我的品味的問題,省略它們會使代碼變得更脆弱,若是稍後將第二個語句添加到「then」子句中,則常見的錯誤是忘記添加新所需的花括號,編譯器沒法捕獲這種錯誤,你會獲得錯誤的結果。segmentfault
if-then-else
語句在「if
」子句求值爲false
時提供輔助執行路徑,若是在自行車不運動時應用制動器,你能夠在applyBrakes
方法中使用if-then-else
語句來執行某些操做,在這種狀況下,操做是簡單地打印一條錯誤消息,指出自行車已經中止。數組
void applyBrakes() { if (isMoving) { currentSpeed--; } else { System.err.println("The bicycle has already stopped!"); } }
如下程序IfElseDemo
根據測試分數的值分配成績:A得分爲90%或以上,B得分爲80%或以上,依此類推。app
class IfElseDemo { public static void main(String[] args) { int testscore = 76; char grade; if (testscore >= 90) { grade = 'A'; } else if (testscore >= 80) { grade = 'B'; } else if (testscore >= 70) { grade = 'C'; } else if (testscore >= 60) { grade = 'D'; } else { grade = 'F'; } System.out.println("Grade = " + grade); } }
該程序的輸出是:編程語言
Grade = C
你可能已經注意到testscore
的值能夠知足複合語句中的多個表達式:76 >= 70
和76 >= 60
,可是,一旦知足條件,就會執行適當的語句(grade ='C';
),而且不評估其他條件。oop
與if-then
和if-then-else
語句不一樣,switch
語句能夠有許多可能的執行路徑,switch
使用byte
、short
、char
和int
原始數據類型,它還適用於枚舉類型(在枚舉類型中討論),String
類,以及一些包含某些基本類型的特殊類:Character
、Byte
、Short
和Integer
(在Number
和String
中討論)。測試
如下代碼示例SwitchDemo
聲明瞭一個名爲month
的int
,其值表示月份,代碼使用switch
語句根據month
的值顯示月份的名稱。
public class SwitchDemo { public static void main(String[] args) { int month = 8; String monthString; switch (month) { case 1: monthString = "January"; break; case 2: monthString = "February"; break; case 3: monthString = "March"; break; case 4: monthString = "April"; break; case 5: monthString = "May"; break; case 6: monthString = "June"; break; case 7: monthString = "July"; break; case 8: monthString = "August"; break; case 9: monthString = "September"; break; case 10: monthString = "October"; break; case 11: monthString = "November"; break; case 12: monthString = "December"; break; default: monthString = "Invalid month"; break; } System.out.println(monthString); } }
在這種狀況下,August
打印到標準輸出。
switch
語句的主體稱爲switch
塊,可使用一個或多個case
或默認標籤來標記switch
塊中的語句,switch
語句計算其表達式,而後執行匹配的case
標籤後面的全部語句。
你還可使用if-then-else
語句顯示月份的名稱:
int month = 8; if (month == 1) { System.out.println("January"); } else if (month == 2) { System.out.println("February"); } ... // and so on
決定是否使用if-then-else
語句或switch
語句是基於可讀性和語句正在測試的表達式,if-then-else
語句能夠基於值或條件的範圍來測試表達式,而switch
語句僅基於單個整數、枚舉值或String
對象來測試表達式。
另外一個興趣點是break
語句,每一個break
語句都會終止封閉的switch
語句。控制流繼續switch
塊後面的第一個語句,break
語句是必要的,由於沒有它們,switch
塊中的語句就會失敗:匹配的case
標籤以後的全部語句都按順序執行,而無論後續case
標籤的表達式,直到遇到break
語句。程序SwitchDemoFallThrough
顯示落入全部switch
塊中的語句,該程序顯示與整數月相對應的月份以及該年份中的月份:
public class SwitchDemoFallThrough { public static void main(String[] args) { java.util.ArrayList<String> futureMonths = new java.util.ArrayList<String>(); int month = 8; switch (month) { case 1: futureMonths.add("January"); case 2: futureMonths.add("February"); case 3: futureMonths.add("March"); case 4: futureMonths.add("April"); case 5: futureMonths.add("May"); case 6: futureMonths.add("June"); case 7: futureMonths.add("July"); case 8: futureMonths.add("August"); case 9: futureMonths.add("September"); case 10: futureMonths.add("October"); case 11: futureMonths.add("November"); case 12: futureMonths.add("December"); break; default: break; } if (futureMonths.isEmpty()) { System.out.println("Invalid month number"); } else { for (String monthName : futureMonths) { System.out.println(monthName); } } } }
這是代碼的輸出:
August September October November December
從技術上講,不須要最後的break
,由於流從switch
語句中退出,建議使用break
,以便更容易修改代碼並減小錯誤,默認部分處理其中一個case
部分未明確處理的全部值。
如下代碼示例SwitchDemo2
顯示了語句如何具備多個case
標籤,代碼示例計算特定月份的天數:
class SwitchDemo2 { public static void main(String[] args) { int month = 2; int year = 2000; int numDays = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: numDays = 31; break; case 4: case 6: case 9: case 11: numDays = 30; break; case 2: if (((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0)) numDays = 29; else numDays = 28; break; default: System.out.println("Invalid month."); break; } System.out.println("Number of Days = " + numDays); } }
這是代碼的輸出:
Number of Days = 29
在Java SE 7及更高版本中,你能夠在switch
語句的表達式中使用String
對象,如下代碼示例StringSwitchDemo
根據名爲month
的String
的值顯示月份的編號:
public class StringSwitchDemo { public static int getMonthNumber(String month) { int monthNumber = 0; if (month == null) { return monthNumber; } switch (month.toLowerCase()) { case "january": monthNumber = 1; break; case "february": monthNumber = 2; break; case "march": monthNumber = 3; break; case "april": monthNumber = 4; break; case "may": monthNumber = 5; break; case "june": monthNumber = 6; break; case "july": monthNumber = 7; break; case "august": monthNumber = 8; break; case "september": monthNumber = 9; break; case "october": monthNumber = 10; break; case "november": monthNumber = 11; break; case "december": monthNumber = 12; break; default: monthNumber = 0; break; } return monthNumber; } public static void main(String[] args) { String month = "August"; int returnedMonthNumber = StringSwitchDemo.getMonthNumber(month); if (returnedMonthNumber == 0) { System.out.println("Invalid month"); } else { System.out.println(returnedMonthNumber); } } }
此代碼的輸出爲8。
將switch
表達式中的String
與每一個case
標籤關聯的表達式進行比較,就好像正在使用String.equals
方法同樣。爲了使StringSwitchDemo
示例不管何種狀況都接受任何month
,month
將轉換爲小寫(使用toLowerCase
方法),而且與case
標籤關聯的全部字符串均爲小寫。
此示例檢查switch
語句中的表達式是否爲null
,確保任何switch
語句中的表達式不爲null
,以防止拋出NullPointerException
。
while
語句在特定條件爲true
時繼續執行語句塊,其語法可表示爲:
while (expression) { statement(s) }
while
語句計算表達式,該表達式必須返回一個布爾值,若是表達式的計算結果爲true
,則while
語句將執行while
塊中的語句,while
語句繼續測試表達式並執行其塊,直到表達式求值爲false
,使用while
語句打印1到10之間的值能夠在如下WhileDemo
程序中完成:
class WhileDemo { public static void main(String[] args){ int count = 1; while (count < 11) { System.out.println("Count is: " + count); count++; } } }
你可使用while
語句實現無限循環,以下所示:
while (true){ // your code goes here }
Java編程語言還提供了do-while
語句,能夠表示以下:
do { statement(s) } while (expression);
do-while
和while
之間的區別在於do-while
在循環的底部而不是頂部計算它的表達式,所以,do
塊中的語句老是至少執行一次,以下面的DoWhileDemo
程序所示:
class DoWhileDemo { public static void main(String[] args){ int count = 1; do { System.out.println("Count is: " + count); count++; } while (count < 11); } }
for
語句for
語句提供了一種迭代一系列值的簡潔方法,程序員常常將其稱爲「for循環」,由於它反覆循環直到知足特定條件,for
語句的通常形式可表示以下:
for (initialization; termination; increment) { statement(s) }
使用此版本的for
語句時,請記住:
initialization
表達式初始化循環,循環開始時,它執行一次。termination
表達式的計算結果爲false
時,循環終止。increment
表達式,這個表達式增長或減小一個值是徹底能夠接受的。如下程序ForDemo
使用for
語句的通常形式將數字1到10打印到標準輸出:
class ForDemo { public static void main(String[] args){ for(int i=1; i<11; i++){ System.out.println("Count is: " + i); } } }
該程序的輸出是:
Count is: 1 Count is: 2 Count is: 3 Count is: 4 Count is: 5 Count is: 6 Count is: 7 Count is: 8 Count is: 9 Count is: 10
注意代碼如何在初始化表達式中聲明變量,此變量的範圍從其聲明擴展到由for
語句控制的塊的末尾,所以它也能夠用在終止和增量表達式中。若是在循環外部不須要控制for
語句的變量,則最好在初始化表達式中聲明該變量。名稱i
,j
和k
一般用於控制循環,在初始化表達式中聲明它們會限制它們的生命週期並減小錯誤。
for
循環的三個表達式是可選的,能夠建立一個無限循環,以下所示:
// infinite loop for ( ; ; ) { // your code goes here }
for
語句還有另外一種用於迭代集合和數組的形式,此形式有時也稱爲加強的for
語句,可用於使循環更緊湊,更易於閱讀,要演示,請考慮如下數組,其中包含數字1到10::
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
如下程序EnhancedForDemo
使用加強型for
循環遍歷數組:
class EnhancedForDemo { public static void main(String[] args){ int[] numbers = {1,2,3,4,5,6,7,8,9,10}; for (int item : numbers) { System.out.println("Count is: " + item); } } }
在此示例中,變量item
保存數字數組中的當前值,該程序的輸出與以前相同:
Count is: 1 Count is: 2 Count is: 3 Count is: 4 Count is: 5 Count is: 6 Count is: 7 Count is: 8 Count is: 9 Count is: 10
咱們建議儘量使用for
語句的這種形式而不是通常形式。
break
語句有兩種形式:標記和未標記,你在前面的switch
語句討論中看到了未標記的形式,你還可使用未標記的break
來終止for
、while
或do-while
循環,如如下BreakDemo
程序所示:
class BreakDemo { public static void main(String[] args) { int[] arrayOfInts = { 32, 87, 3, 589, 12, 1076, 2000, 8, 622, 127 }; int searchfor = 12; int i; boolean foundIt = false; for (i = 0; i < arrayOfInts.length; i++) { if (arrayOfInts[i] == searchfor) { foundIt = true; break; } } if (foundIt) { System.out.println("Found " + searchfor + " at index " + i); } else { System.out.println(searchfor + " not in the array"); } } }
該程序在數組中搜索數字12,break
語句在找到該值時終止for
循環,而後,控制流轉移到for
循環後的語句,該程序的輸出是:
Found 12 at index 4
未標記的break
語句終止最內層的switch
、for
、while
或do-while
語句,但帶標籤的break
終止外部語句。如下程序BreakWithLabelDemo
與前一個程序相似,但使用嵌套for
循環來搜索二維數組中的值,找到該值後,帶標籤的break
將終止外部for
循環(標記爲「search」):
class BreakWithLabelDemo { public static void main(String[] args) { int[][] arrayOfInts = { { 32, 87, 3, 589 }, { 12, 1076, 2000, 8 }, { 622, 127, 77, 955 } }; int searchfor = 12; int i; int j = 0; boolean foundIt = false; search: for (i = 0; i < arrayOfInts.length; i++) { for (j = 0; j < arrayOfInts[i].length; j++) { if (arrayOfInts[i][j] == searchfor) { foundIt = true; break search; } } } if (foundIt) { System.out.println("Found " + searchfor + " at " + i + ", " + j); } else { System.out.println(searchfor + " not in the array"); } } }
這是該程序的輸出。
Found 12 at 1, 0
break
語句終止帶標籤的語句,它不會將控制流轉移到標籤上,控制流在標記(終止)語句以後當即轉移到語句。
continue
語句跳過for
、while
或do-while
循環的當前迭代,未標記的形式跳到最內層循環體的末尾,並計算控制循環的布爾表達式。如下程序ContinueDemo
逐步執行字符串,計算字母「p」的出現次數,若是當前字符不是p,則continue
語句將跳過循環的其他部分並繼續執行下一個字符,若是是「p」,程序會增長字母數。
class ContinueDemo { public static void main(String[] args) { String searchMe = "peter piper picked a " + "peck of pickled peppers"; int max = searchMe.length(); int numPs = 0; for (int i = 0; i < max; i++) { // interested only in p's if (searchMe.charAt(i) != 'p') continue; // process p's numPs++; } System.out.println("Found " + numPs + " p's in the string."); } }
這是該程序的輸出:
Found 9 p's in the string.
要更清楚地看到此效果,請嘗試刪除continue
語句並從新編譯,當你再次運行程序時,計數將是錯誤的,說它找到35個p而不是9個。
標記的continue
語句跳過標記有給定標籤的外循環的當前迭代,如下示例程序ContinueWithLabelDemo
使用嵌套循環來搜索另外一個字符串中的子字符串,須要兩個嵌套循環:一個遍歷子字符串,一個迭代搜索的字符串,如下程序ContinueWithLabelDemo
使用標記形式的continue
來跳過外部循環中的迭代。
class ContinueWithLabelDemo { public static void main(String[] args) { String searchMe = "Look for a substring in me"; String substring = "sub"; boolean foundIt = false; int max = searchMe.length() - substring.length(); test: for (int i = 0; i <= max; i++) { int n = substring.length(); int j = i; int k = 0; while (n-- != 0) { if (searchMe.charAt(j++) != substring.charAt(k++)) { continue test; } } foundIt = true; break test; } System.out.println(foundIt ? "Found it" : "Didn't find it"); } }
這是該程序的輸出。
Found it
最後一個分支語句是return
語句,return
語句從當前方法退出,控制流返回到調用方法的位置,return
語句有兩種形式:一種是返回值,另外一種是不返回值,要返回值,只需將值(或計算值的表達式)放在return
關鍵字以後。
return ++count;
返回值的數據類型必須與方法聲明的返回值的類型匹配,當方法聲明爲void
時,請使用不返回值的return
形式。
return;
類和對象課程將涵蓋你須要瞭解的有關編寫方法的全部內容。
if-then
語句是全部控制流語句中最基本的語句,它告訴程序只有在特定測試評估爲true
時才執行某段代碼。if-then-else
語句在「if」子句求值爲false
時提供輔助執行路徑,與if-then
和if-then-else
不一樣,switch
語句容許任意數量的可能執行路徑。while
和do-while
語句在特定條件爲true
時不斷執行語句塊,do-while
和while
之間的區別在於do-while
在循環的底部而不是頂部計算它的表達式,所以,do
塊中的語句老是至少執行一次。for
語句提供了一種迭代一系列值的簡潔方法,它有兩種形式,其中一種用於循環集合和數組。