1.正文
因为想要了解编译器是如何实现foreach功能的,就先写一个foreach循环,看看字节码长啥样。
public class ForEach {
List<String> list;
public void display1(){
for(String s : list){
System.out.println(s);
}
}
}
字节码就长下面这个样子:
// Method descriptor #10 ()V /*V代表返回值是void*/
// Stack: 2, Locals: 3 /*操作数栈需要2个slot,局部变量表需要3个slot*/
public void display1();
0 aload_0 [this] /*将this指针推至栈顶*/
1 getfield ambigous.ForEach.list : java.util.List [19] /*获得域List对象,压入栈顶*/
4 invokeinterface java.util.List.iterator() : java.util.Iterator [21] [nargs: 1] /*调用interface的iterator方法获得iterator对象*/
9 astore_2 /*将其存到局部变量表的第三个slot中(此时第一个是this,第二个空)*/
10 goto 30 /*跳转*/
13 aload_2 /*将iterator对象推到栈顶*/
14 invokeinterface java.util.Iterator.next() : java.lang.Object [27] [nargs: 1] /*调用iterator的next方法*/
19 checkcast java.lang.String [33]/*checkcast类型安全检查*/
22 astore_1 [s] /*将s存到第二块slot*/
23 getstatic java.lang.System.out : java.io.PrintStream [35] /*获取静态System.out对象*/
26 aload_1 [s] /*将s推到栈顶*/
27 invokevirtual java.io.PrintStream.println(java.lang.String) : void [41] /*调用out.println方法*/
30 aload_2 /*将iterator对象推到栈顶*/
31 invokeinterface java.util.Iterator.hasNext() : boolean [47] [nargs: 1] /*调用iterator.hasNext方法*/
36 ifne 13 /*如果结果非0,即true,跳转*/
39 return /*返回*/
可以看出对于foreach的执行最终转换成了对iterator的调用。那么我们再对比下显示使用iterator代码的字节码:
public class ForEach {
List<String> list;
public void display1(){
for(String s : list){
System.out.println(s);
}
}
public void display2(){
Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
字节码:
// Method descriptor #10 ()V
// Stack: 2, Locals: 2
public void display2();
0 aload_0 [this]
1 getfield ambigous.ForEach.list : java.util.List [19]
4 invokeinterface java.util.List.iterator() : java.util.Iterator [21] [nargs: 1]
9 astore_1 [it]
10 goto 28
13 getstatic java.lang.System.out : java.io.PrintStream [35]
16 aload_1 [it]
17 invokeinterface java.util.Iterator.next() : java.lang.Object [27] [nargs: 1]
22 checkcast java.lang.String [33]
25 invokevirtual java.io.PrintStream.println(java.lang.String) : void [41]
28 aload_1 [it]
29 invokeinterface java.util.Iterator.hasNext() : boolean [47] [nargs: 1]
34 ifne 13
37 return
看~是不是惊人的相似!其实并不惊人,一切都在预料之中。哈哈。
那么为什么此时局部变量表只需要2个slot就够了呢?
因为第一段代码中slot先后存了this指针、list中的元素即局部变量s、iterator对象;而第二段代码中没有String的临时变量,只有this指针和iterator对象it。
那么两段代码栈为什么都用了两个slot呢?
因为其实第一段代码在23-26的时候栈才存满,栈底是out,栈顶是s。其他时候栈都未满。第二段在13-16的时候栈满,栈底依旧out,栈顶是iterator对象it。
2.References
java forEach实现原理
http://blog.csdn.net/a596620989/article/details/6930479