JITがコードをどのように最適化するか(Javaのどの実装、どのOSなど)を言うのは難しいです。ここでの主なポイントは、for-each構文がイテレータ構文を使用するのと同じバイトコードにコンパイルされることです。こことここを参照してください。イテレータ構文を使用する主な理由は、反復中にアイテムを削除するためです。Iteratorインターフェースのremoveメソッドはオプションであることに注意してください。
バイトコードを自分で確認するために、いくつかの簡単な例を作成しました。
配列の反復ごとに
// compiled .class file is 585 bytes
public class ForEachLoop {
public static void main(String[] args) {
for(String s : args){
System.out.println(s);
}
}
}
// byte code for main method
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=5, Args_size=1
0: aload_0
1: dup
2: astore 4
4: arraylength
5: istore_3
6: iconst_0
7: istore_2
8: goto 26
11: aload 4
13: iload_2
14: aaload
15: astore_1
16: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #22; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: iinc 2, 1
26: iload_2
27: iload_3
28: if_icmplt 11
31: return
LineNumberTable:
line 4: 0
line 5: 16
line 4: 23
line 7: 31
LocalVariableTable:
Start Length Slot Name Signature
0 32 0 args [Ljava/lang/String;
16 7 1 s Ljava/lang/String;
配列のインデックスループ
// compiled .class file is 554 bytes
public class ArrayLoop {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
// byte code for main method
public static void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=1
0: iconst_0
1: istore_1
2: goto 17
5: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
8: aload_0
9: iload_1
10: aaload
11: invokevirtual #22; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: iinc 1, 1
17: iload_1
18: aload_0
19: arraylength
20: if_icmplt 5
23: return
LineNumberTable:
line 4: 0
line 5: 5
line 4: 14
line 7: 23
LocalVariableTable:
Start Length Slot Name Signature
0 24 0 args [Ljava/lang/String;
2 21 1 i I
配列反復バイトコードがよりコンパクトであることがわかります(正確には31バイト)。