【java】foreach是如何实现的?

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


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值