【java】foreach是如何实现的?
2016-04-06 22:53
519 查看
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
相关文章推荐
- 为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?
- eclipse Android模拟器无法创建
- 对java中synchronized的认识
- [编程题] 生成格雷码(JAVA实现)
- Spring-3.2.4 + Quartz-2.2.0集成实例
- java RMI 分布式简单应用
- 04_从磁盘读取Java程序,并显示在屏幕上
- 使用Eclipse导出doc文档
- ibatis使用及在spring中的bean配置
- eclipse完美配置PHP开发环境
- springMVC学习
- IDE介绍以及Eclipse的简单使用
- struts2表单提交时总是返回input
- java字符串常用方法
- Java集合详解(一):Collection
- Jqgrid+Spring实现的增删改查(一)
- 设计模式---策略模式
- Maven搭建SpringMVC+Mybatis项目时遇到的问题记录
- Java之数据库篇
- Java serialable序列化高级详解