Java中,for-each循環(huán)簡(jiǎn)化了任何Collection或array的遍歷過(guò)程,但并不是每個(gè)Java程序員都了解本文將要描述的for-each 循環(huán)的一些細(xì)節(jié)。與 Java5 發(fā)布的其他術(shù)語(yǔ):釋放別名泛型,自動(dòng)封裝和可變參數(shù)不同,Java開(kāi)發(fā)者對(duì)for-each循環(huán)的使用比任何其他特性更加頻繁,但當(dāng)問(wèn)及高級(jí)的for-each循環(huán)怎樣工作,或什么是在for-each循環(huán)中使用Collection時(shí)的基本需求時(shí),就不是每個(gè)人都能夠回答的了。
本篇教程和例子旨在通過(guò)深入研究for-each 循環(huán)中幾個(gè)有趣的難題來(lái)填補(bǔ)上述空白(說(shuō)明上述問(wèn)題)。好了,不再贅述,一起看看我們?cè)贘ava5 for-each循環(huán)的第一個(gè)問(wèn)題。
高級(jí)循環(huán)問(wèn)題 1
考慮下面這段遍歷一個(gè)用戶(hù)自定義的aggregator或collection類(lèi)的代碼,這段代碼將會(huì)打印出什么,拋出異常還是編譯器錯(cuò)誤:
下面是我們的CustomCollection類(lèi),這是個(gè)參數(shù)為泛型的類(lèi),與任何其他的Collection類(lèi)相似,依靠于ArrayList并提供從Collection中添加和刪除項(xiàng)的方法。
答案:
上述代碼將無(wú)法通過(guò)編譯,這是因?yàn)槲覀兊腃ustomCollection類(lèi)沒(méi)有實(shí)現(xiàn)java.lang.Iterable接口,編譯期錯(cuò)誤如下:
從中了解到的一個(gè)有趣的事實(shí)是:for-each循環(huán)僅應(yīng)用于實(shí)現(xiàn)了Iterable接口的Java array和Collection類(lèi),而且既然所有內(nèi)置Collection類(lèi)都實(shí)現(xiàn)了java.util.Collection接口,已經(jīng)繼承了Iterable,這一細(xì)節(jié)通常會(huì)被忽略,這點(diǎn)可以在Collection接口的類(lèi)型聲明“ public interface Collection extends Iterable”中看到。所以為了解決上述問(wèn)題,你可以選擇簡(jiǎn)單地讓CustomCollection實(shí)現(xiàn)Collection接口或者繼承AbstractCollection,這是默認(rèn)的通用實(shí)現(xiàn)并展示了如何同時(shí)使用抽象類(lèi)和接口以獲取更好的靈活性。現(xiàn)在讓我們來(lái)看看for-each循環(huán)的第二個(gè)難題:
Java for-each循環(huán)的第二個(gè)難題:
在下面的代碼示例將會(huì)拋出ConcurrentModificationException異常。這里我們使用標(biāo)準(zhǔn)iterator和for-each循環(huán)遍歷ArrayList,隨后刪除元素,你需要找出哪段代碼將會(huì)拋出ConcurrentModificationException ,為什么?請(qǐng)注意,答案可能是兩個(gè)都會(huì),都不會(huì)或其中之一。
大約70%的Java開(kāi)發(fā)者都會(huì)說(shuō)第一個(gè)代碼塊會(huì)拋出ConcurrentModificationException異常,因?yàn)槲覀儧](méi)有用iterator的remove方法來(lái)刪除元素,而是使用ArrayList的 remove()方法。但是,沒(méi)有多少Java開(kāi)發(fā)者會(huì)說(shuō)出for-each循環(huán)也會(huì)出現(xiàn)同樣的問(wèn)題,因?yàn)槲覀冊(cè)谶@里沒(méi)有使用iterator。事實(shí)上,第二個(gè)代碼片段也會(huì)拋出ConcurrentModificationException異常,這點(diǎn)在解決了第一個(gè)困惑之后就變得很明顯了。既然for-each循環(huán)內(nèi)部使用了Iterator來(lái)遍歷Collection,它也調(diào)用了Iterator.next(),這會(huì)檢查(元素的)變化并拋出ConcurrentModificationException。你可以從下面的輸出中了解到這點(diǎn),在注釋掉第一個(gè)代碼段后,當(dāng)你運(yùn)行第二個(gè)代碼段時(shí)會(huì)得到下面的輸出。
以上就是關(guān)于Java5 for-each循環(huán)的全部?jī)?nèi)容。我們已經(jīng)看到了Java程序員在編寫(xiě)遍歷Collection類(lèi)的代碼時(shí)產(chǎn)生的很多問(wèn)題,特別是在遍歷collection的同時(shí)刪除元素的時(shí)候。請(qǐng)牢記,在從任何Collection(例如Map、Set或List)中刪除對(duì)象時(shí)總要使用Iterator的remove方法,也請(qǐng)謹(jǐn)記for-each循環(huán)只是標(biāo)準(zhǔn)Iterator代碼標(biāo)準(zhǔn)用法之上的一種語(yǔ)法糖(syntactic sugar)而已。
譯者注:語(yǔ)法糖(syntactic sugar),也譯為糖衣語(yǔ)法,是由英國(guó)計(jì)算機(jī)科學(xué)家彼得?約翰?蘭達(dá)-Peter J. Landin發(fā)明的一個(gè)術(shù)語(yǔ),指計(jì)算機(jī)語(yǔ)言中添加的某種語(yǔ)法,這種語(yǔ)法對(duì)語(yǔ)言的功能并沒(méi)有影響,但是更方便程序員使用。通常來(lái)說(shuō)使用語(yǔ)法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注