|
|
如果你要走訪陣列中所有元素,通常你會這麼寫: public void go(int[] arr) { for(int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } 事實上很多時候,從頭到尾走訪一個陣列(或Collection)中所有元素,是很常見的需求,上面的寫法並沒有錯,只不過索引資訊基本上是不需要的,硬要寫是很冗長的事。 在J2SE 5.0之後,引進了foreach新語法,上例你可以這麼改寫: public void go(int[] arr) { for(int element : arr) { System.out.println(element); } } 這個語法其實不僅限於陣列,還可以用在List、Set等。例如若是List實作物件,可以這麼寫: public void go(List<String> list) { for(String element : list) { System.out.println(element); } } 如果是Set也是可以的,例如: public void go(Set<String> set) { for(String element : set) { System.out.println(element); } } 事實上,只要是Collection介面的實作物件,都可以用foreach語法: public void go(Collection<String> collection) { for(String element : collection) { System.out.println(element); } } Java的foreach語法,其實是編譯器給的語法蜜糖。如果foreach要走訪的是陣列,事實上,編譯器會自動展開為以下的程式碼: public void go(int ai[]) { int ai1[] = ai; int i = ai1.length; for(int j = 0; j < i; j++) { int k = ai1[j]; System.out.println(k); } } 若foreach運用在Collection的實作物件上,其實編譯器會展開為: public void go(Collection collection) { String s; for(Iterator iterator = collection.iterator(); iterator.hasNext(); System.out.println(s)) s = (String)iterator.next(); } 無論是Collection、List或Set,展開後皆利用iterator()方法傳回Iterator物件,並利用Iterator來移動、傳回下一個物件,這是 Iterator 模式 的實現。 在J2SE 1.4之前,Collection介面上直接定義了iterator()方法必須實作,因此所有Collection實作物件,皆需實作iterator ()。在J2SE 5.0之後,引進了Iterable介面,在介面中定義了iterator()方法,該方法必須傳回Iterator物件,而Collection介面繼 承了Iterable介面,因此所有Collection實作物件,皆需實作iterator(),因此所有Collection實作物件,都可以搭配使用foreach語法。 然而並非只有Collection介面的實作物件,才可以搭配foreach語法,事實上,由於Iterable介面的引進,使得只要是實作Iterable介面的物件,皆可搭配foreach語法來使用。例如:
import java.util.Iterator; IterableString類別實作了Iterable介面,因此你可以像以下這麼搭配foreach:
public class Main {若你反組譯程式,會發現編譯器作了這些事: Character c; for(Iterator iterator = str.iterator(); iterator.hasNext(); System.out.println(c)) c = (Character)iterator.next(); |