1. 程式人生 > >Java流程控制的陷阱——for迴圈和foreach迴圈的陷阱

Java流程控制的陷阱——for迴圈和foreach迴圈的陷阱

5、for迴圈的陷阱

5、1 分號的問題

public class SemicolonRight {
	public static void main(String[] args) {
		for ( int j = 1 , i = 0 ; i < 5 && j < 20 ; i++ , j *=2 ) {
			System.out.println(i + "-->" + j);
		}
	}
}
輸出結果為: 0-->1
1-->2
2-->4
3-->8
4-->16
       根據Java語言規範,for迴圈裡有且只有兩個分號作為分隔符。第一個分號之前的是初始化條件;兩個分號中間的部分是一個返回boolean的邏輯表示式,當它返回true是for迴圈才會執行下一次迴圈;第二個分號之後的是迴圈迭代部分,每次迴圈結束後會執行迴圈迭代部分。
注意:for迴圈的初始化條件可以同時定義多個變數,但由於它只能接受一條語句,因此這兩個變數的資料型別應該相同。

5、2 迴圈計數器的問題

public class CareForCount {
	public static void main(String[] args) {
		for ( int i = 0 ; i < 10 ; i ++ ) {
			System.out.println("i的值為:" + i);
			i *= 0.1;
		}
	}
}
       上面程式試圖控制迴圈10次,但是編譯、執行上面的程式會發現輸出一遍
i的值為:0 ”,然後一直輸出“i的值為:1”,並且是一個死迴圈。下面分析一下程式執行的過程:程式開始時i=0,程式輸出 i的值為:0 ”,然後執行i*=0.1;,這行語句相當於i = (int)(i * 0.1);,得到的結果依然是i=0。執行完迭代條件後i=1,因此程式看到輸出i的值為:1”,接下來執行i*=0.1;,這行程式碼使i再次變為0。以此類推,每次執行完迴圈體後i的值總是為0,執行完迴圈迭代部分之後i的值總是為1,因此這個程式就是一個死迴圈。 提示:儘量避免在迴圈體中改變迴圈計數器的值,如果迴圈體內需要根據訪問修改迴圈計數器的值,則可以考慮額外定義一個新變數用來儲存修改過的值。

5、3 浮點數作為迴圈計數器的問題

public class FloatCount {
	public static void main(String[] args) {
		final int START = 99999999;
		for ( float i = START ; i < START + 50 ; i ++ ) {
			System.out.println("i的值:" + i);
		}
	}
}
       編譯並執行上面的程式,一直輸出“i的值:1.0E9”,並且是一個死迴圈。導致這個結果的原因是:定義的START是一個int型別整數,而且數值還比較大,當程式把這個int型別整數賦給float型別變數時,float型別變數無法精確記錄這個值,會導致精度丟失。

6、foreach迴圈的陷阱

       從Java5開始,Java增加了foreach迴圈用於遍歷陣列、集合的每個元素。使用foreach迴圈遍歷陣列和集合元素時, 無須獲得陣列和集合長度,也無須根據索引來訪問陣列元素和集合元素,foreach迴圈自動遍歷陣列和集合的每個元素。當使用foreach迴圈來迭代輸出陣列元素或集合元素時,系統將陣列元素、集合元素的 副本傳給迴圈計數器。由於foreach迴圈中的迴圈計數器本身並不是陣列元素、集合元素,它只是一箇中間變數, 臨時儲存了正在遍歷的陣列元素、集合元素,因此通常不要對迴圈變數進行賦值,雖然這種賦值在語法上是允許的,但是沒有實際意義,而且容易引起錯誤。
import java.util.ArrayList;
import java.util.List;

public class ForEacheErrorTest {
	public static void main(String[] args) {
		List<String> books = new ArrayList<>();
		books.add("book1");
		books.add("book2");
		books.add("book3");
		for (String book : books) {
			book = "BOOK";
			System.out.println(book);
		}
		System.out.println(books);
	}
}
輸出結果為: BOOK
BOOK
BOOK
[book1, book2, book3] 注意:使用foreach迴圈迭代陣列、集合時,迴圈計數器只是儲存了當前正在遍歷的陣列元素、集合元素的值,並不是陣列元素、集合元素本身,因此不要對foreach迴圈的迴圈計數器進行賦值。