従来の Java 言語の for 文は、C言語で使われているごく一般的な for 文でした。 新しい Java 言語では、この for 文が拡張され、配列やコレクションの先頭から末尾までを安全に処理することができるようになりました。 これをfor-each文と呼びます。 for-each 文は、次のように記述します。
for (型 変数名 : コレクション) 文
これが、for-each 文の構文です。 記号 : の手前に変数を指定し、右側に java.util.Iterator を提供する新しい java.lang.Iterable インタフェースを実装するオブジェクトを指定しなければなりません。 Iterable インタフェースは次のように定義されています。
public interface Iterable<T>
このインタフェースには java.util.Iterater オブジェクトを返す iterater() メソッドを宣言しています。
java.lang.Iterable インタフェースは Java コレクション API の java.util.Collection インタフェースが継承しています。 ArrayList など、一般的に利用されている動的配列オブジェクトは Iterable インタフェースを実装していると考えることができ、foe-each 文で安全に利用することができます。
この for 文は、指定したコレクションオブジェクトが管理している配列の先頭から末尾までを確実に処理することができます。 文を実行する前に、コレクションの先頭から順に : の左側に宣言した変数に要素が代入されます。
for (Object element : list) { System.out.println(element); }
例えばこのように記述することで、Iterable インタフェースを実装するオブジェクト list で管理されている Iterator をすべて監視することができます。 foe-each 文は Iterable インタフェースの iterator() メソッドから Iterator オブジェクトを取得し、hasNext() メソッドが false を返すまで next() が返す要素を element に代入して文を実行します。 文が実行されるたびに Iterator オブジェクトの next() メソッドが実行されるため、element 変数には常に次の要素が格納されています。 結果として、Iterator の全ての要素を確実に監視することができるのです。
class MyList implements Iterable<Integer> , java.util.Iterator<Integer> { private int index , max; public MyList(int count) { max = count; } public java.util.Iterator<Integer> iterator() { return this; } public boolean hasNext() { return index < max; } public Integer next() { return new Integer(index++); } public void remove() {} } class Test { public static void main(String args[]) { MyList list = new MyList(10); for(Integer i : list) { System.out.println("i = " + i); } } }
このプログラムは、Iterable インタフェースを独自実装した MyList クラスを foe-each 文にかけて全ての要素が適切に処理されることを証明してます。 MyList クラスは、Iterable と Iterater インタフェースを実装し、iterator() メソッドから Iterater を実装している自分自身を返します。
MyList クラスは、コンストラクタの引数に指定された数だけ Integer オブジェクトを要素として返す動的な配列です。 next() メソッドが要求されるたびに、index が max 以下であれば、現在の index を Integer オブジェクトに変換して値を返すだけの単純なクラスです。
for-each 文は、 Iterable インタフェースを実装している list オブジェクトから iterator() メソッドを呼び出して、ここから得られた Iterator オブジェクトの各要素を繰り返し実行します。
class Test { public static void main(String args[]) { java.util.Collection<String> list = new java.util.ArrayList<String>(); list.add("1 : シエルさんカレーです"); list.add("2 : あんまんは命の源"); list.add("3 : これが憧れのバナナパフェ!"); list.add("4 : マーボー豆腐、食うか?"); for(String obj : list) { System.out.println(obj); } } }
C:\Development\Java>java Test 1 : シエルさんカレーです 2 : あんまんは命の源 3 : これが憧れのバナナパフェ! 4 : マーボー豆腐、食うか?
新しい Java Framework は Generics に対応しているため、Object 型以外の動的な配列の要素もコンパイラがチェックすることができます。 Collection インタフェースはパラメータ化されているため、上記のプログラムの場合はイテレータから確実に String 型を得ることができるということをコンパイル時に確認できます。
同様に、配列からも for-each 文で要素を処理することができます。
class Test { public static void main(String args[]) { int [] ary = new int[] { 1, 2, 3, 4, 5 }; for(int element : ary) { System.out.println("element = " + element); } } }
このプログラムを実行すれば、for-each 文で ary 配列変数の ary[0] 〜 ary[4] までの要素が列挙されることを確認することができるでしょう。