一個Java增強型for循環的易犯錯誤,你注意到了嗎?

我們知道,在Java語言中有三種循環,分別是while循環,do…while循環和for循環。其實,從JDK1.5開始,又引入了一種增強型for循環,這種新型的for循環主要是用來遍歷數組或集合的,它的格式非常簡單,下圖展示了增強型for循環的基本結構:

增強型for循環被設計出來就是爲了遍歷數組或者是集合的,所以在循環中都會指定一個數組或者是集合。爲了方便程序員編碼,增強型for循環不再通過”下標”的形式訪問數組或集合中的元素,而是把依次從數組或集合取出元素,並命名爲i,這樣,程序員就可以直接操作元素i,從而大大簡化了代碼。爲了方便表述,我們把元素i稱之爲“當前元素”。下面來看一個簡單例子:

在這個增強型for循環中,指定的數組叫做array。每次循環,都從array數組中取出一個元素並命名爲i,之後打印元素i的值。這裏特意提醒各位小夥伴一下:循環中出現的”i”並非數組的下標,而是一個數組元素,也就是我們前面所說的”當前元素“。這段程序運行結果是”1 2 3 “。如果使用傳統的for循環也能達到同樣的效果,代碼如下:

僅從以上兩段代碼的運行結果來看,似乎增強型for循環和傳統for循環沒有什麼區別。但是,如果把以上兩段代碼稍作修改,運行結果就會迥然不同。我們把第一段代碼改爲如下形式:

爲了表述方便,我們把第一段修改後的代碼稱之爲”代碼①”。之後,把原來的第二段代碼修改爲以下形式:

同理,我們把修改後的第二段代碼稱爲”代碼②”。”代碼①”和”代碼②”都是在它們原來的版本基礎之上添加了一段循環修改數組元素值的操作。

但是,再次運行程序就會發現,”代碼①”的運行結果仍然是”1 2 3 ”,而”代碼②”的運行結果是”3 4 5 ”,也就是說”代碼①”中修改數組元素值的操作並沒有起作用。這是爲什麼呢?就是因爲:”代碼①”中所謂的”當前元素”i其實是一個作用域僅限於循環自身的局部變量,每次循環開始的時候都要重新定義這個變量,並且重新用數組元素對變量i進行賦值。i的值來源於數組元素,但i本質上並不是數組元素本身,它只是數組元素的副本,因此修改i並不能改變數組元素的值。在”代碼①”的第一個循環中,修改的就是局部變量i的值,而並非數組元素本身的值。因此,在”代碼①”的第二個循環中打印”當前元素”,實際上是再次把數組元素的值賦值給局部變量i並且打印,既然數組元素的值並未改變,打印出的結果當然是原數組中的”1 2 3”。

再來看”代碼②”,”代碼②”中的第一個循環是通過下標的直接找到了真實的數組元素並且做了修改,每次操作都修改的是實實在在的數組元素,而不是數組元素的副本!所以程序運行到第二個循環中,打印的是修改後的數組元素。

以上講解,就是爲了讓小夥伴們明白:增強型for循環中的那個”當前元素i”,其實是一個臨時的局部變量,它只是數組元素的副本,而非數組元素本身。但是,我們所舉的例子中,數組的類型屬於基礎數據類型。那麼,如果數組並非基礎類型,而是引用類型,使用增強型for循環能否修改數組元素呢?請看以下代碼:

在這段代碼中,首先定義了一個Num類,在Num類中有一個int型的屬性x,我們通過構造方法初始化x的值。代碼的Test類中,在主方法裏定義了一個Num類型的數組array,這個數組顯然是一個引用類型數據的數組。數組中的引用分別指向了3個Num類型的對象,這三個對象的x屬性值分別是1,2,3。第一個for循環修改了數組中每個Num對象的x屬性值,第二個循環依次打印出每個Num對象的x屬性值,程序運行結果是在控制檯上輸出了”3 4 5”。這說明增強型for循環在遍歷引用類型的數組時,通過”當前元素”可以修改數組中元素的狀態,這又是爲什麼呢?原因其實也很簡單,雖然”當前元素”n本質上也只是一個作用域僅限於循環內部的局部引用,但是,每次循環過程中,它都實實在在的指向了一個真實的數組元素,所以這個局部引用作用域雖小,但通過它卻能夠完成修改數組元素對象屬性值的操作。

 

另外再強調一點,無論增強型for循環所遍歷的是基礎數據類型的數組,還是引用類型的數組(或集合),都要保證”當前元素”與數組中真實元素的“類型兼容性”,否則程序就會報錯。比如說,我們通過一個增強型for循環操作一個int型數組時,可以把”當前元素”i設定爲double類型,原因就是數組中int型的元素可以賦值給double類型的局部變量。但反過來,通過增強型for循環操作一個double型數組時,不能把”當前元素”i的類型設定爲int類型,就是因爲按照Java語法,無法完成由double到int的自動轉換。同理,操作一個String型數組時,可以把”當前元素”的類型設定爲Object,反之則無法通過編譯。

 

希望通過這篇文章能夠讓小夥伴們能更深入瞭解Java增強型for循環的本質。

 

如想系統學習Java編程,可以點擊這裏觀看我在本站的視頻課程,有問題也可以加入我的QQ羣291839907一起討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章