转 java foreach实现原理

简介:

java.util.List实现了java.lang.Iterable接口.

jdk api文档中是这样描述Iterable接口的:实现这个接口允许对象成为 "foreach" 语句的目标。不过咋一看Iterable接口并没啥特别之处,只是定义了一个迭代器而已。

?
1
2
3
4
5
6
7
8
public  interface  Iterable<T> {  
     /** 
      * Returns an iterator over a set of elements of type T. 
      *  
      * @return an Iterator. 
      */  
     Iterator<T> iterator();  
}

究竟是如何实现foreach的呢,想想可能是编译器做了优化,就看了下最终编译成的字节码:

?
1
2
3
4
5
6
7
8
public  class  Iterable_eros {  
     List<String> strings;  
     public  void  display(){  
         for (String s : strings){  
             System.out.println(s);  
         }  
     }      
}

相应的字节码为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  void  display (){  
line0    : aload_0    
            getfield  java.util.List my.lang.Iterable_eros.strings  
            invokeinterface  java.util.Iterator java.util.List.iterator()  1  
            astore_2    
            goto   line30  
line13   : aload_2    
            invokeinterface  java.lang.Object java.util.Iterator.next()  1  
            checkcast  java.lang.String  
            astore_1    
line23   : getstatic  java.io.PrintStream java.lang.System.out  
            aload_1    
line27   : invokevirtual   void  java.io.PrintStream.println(java.lang.String)  
line30   : aload_2    
            invokeinterface   boolean  java.util.Iterator.hasNext()  1  
            ifne  line13  
line39   :  return

果然没猜错哈!可以看到,foreach语法最终被编译器转为了对Iterator.hasNext()和对Iterator.next()的调用。而作为使用者的我们, jdk并没用向我们暴露这些细节,我们甚至不需要知道Iterator的存在,认识到jdk的强大之处了吧。

为了证实自己的想法,又用Iterator写了个遍历List的方法查看了字节码,果然跟foreach的形式基本一样,当然这是后话~

?
1
2
3
4
5
6
7
8
9
10
11
public  void  display(){  
     for (String s : strings){  
         System.out.println(s);  
     }  
           
     Iterator<String> iterator = strings.iterator();  
     while (iterator.hasNext()){  
         String s = iterator.next();  
         System.out.println(s);  
     }  
}

用相应的字节码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public  void  display (){  
line0    : aload_0    
            getfield  java.util.List my.lang.Iterable_eros.strings  
            invokeinterface  java.util.Iterator java.util.List.iterator()  1  
            astore_2    
            goto   line30  
line13   : aload_2    
            invokeinterface  java.lang.Object java.util.Iterator.next()  1  
            checkcast  java.lang.String  
            astore_1    
line23   : getstatic  java.io.PrintStream java.lang.System.out  
            aload_1    
line27   : invokevirtual   void  java.io.PrintStream.println(java.lang.String)  
line30   : aload_2    
            invokeinterface   boolean  java.util.Iterator.hasNext()  1  
            ifne  line13  
            aload_0    
            getfield  java.util.List my.lang.Iterable_eros.strings  
            invokeinterface  java.util.Iterator java.util.List.iterator()  1  
            astore_1    
line49   :  goto   line69  
line52   : aload_1    
            invokeinterface  java.lang.Object java.util.Iterator.next()  1  
            checkcast  java.lang.String  
            astore_2    
line62   : getstatic  java.io.PrintStream java.lang.System.out  
            aload_2    
line66   : invokevirtual   void  java.io.PrintStream.println(java.lang.String)  
line69   : aload_1    
            invokeinterface   boolean  java.util.Iterator.hasNext()  1  
            ifne  line52  
line78   :  return

这边还发现一个比较有趣的现象:在取Iterator.next()之后并在把该值load进内容栈之前,编译器调用了checkcast  java.lang.String方法来进行类型安全检查,jdk应该是采用这个来检测并抛出ClassCastException的。

目录
相关文章
|
1月前
|
存储 算法 Java
【Java集合类面试八】、 介绍一下HashMap底层的实现原理
HashMap基于hash算法,通过put和get方法存储和获取对象,自动调整容量,并在碰撞时用链表或红黑树组织元素以优化性能。
|
30天前
|
安全 Java UED
Java线程池的实现原理及其在业务中的最佳实践
本文讲述了Java线程池的实现原理和源码分析以及线程池在业务中的最佳实践。
|
1月前
|
存储 Java 索引
Java中foreach遍历数组如何拿到想要的值
总结来说,通过foreach循环遍历数组并获取所需的值是一种简单且代码清晰的操作,特别适用于只需访问集合或数组中的每个元素且不需要元素索引或修改集合的场景。在实际编程中,根据场景需求合理选择循环类型,可大大提高代码的可读性与效率。
77 4
|
1月前
|
存储 安全 Java
解锁Java并发编程奥秘:深入剖析Synchronized关键字的同步机制与实现原理,让多线程安全如磐石般稳固!
【8月更文挑战第4天】Java并发编程中,Synchronized关键字是确保多线程环境下数据一致性与线程安全的基础机制。它可通过修饰实例方法、静态方法或代码块来控制对共享资源的独占访问。Synchronized基于Java对象头中的监视器锁实现,通过MonitorEnter/MonitorExit指令管理锁的获取与释放。示例展示了如何使用Synchronized修饰方法以实现线程间的同步,避免数据竞争。掌握其原理对编写高效安全的多线程程序极为关键。
50 1
|
2月前
|
Java 开发者
Java实现基于清除后分配规则的垃圾回收器及其实现原理
通过上述简化模型的实现,我们可以理解基于清除后分配规则的垃圾回收器的基本工作原理。实际上,现代JVM中的垃圾回收器比这个例子复杂得多,它们可能包括更多阶段、优化策略,以及不同类型的垃圾回收器协同工作。然而,理解这一基本概念对于深入理解垃圾回收机制和内存管理非常有帮助。
18 3
|
3月前
|
存储 算法 Java
滚雪球学Java(65):深入理解Java中的Map接口:实现原理剖析
【6月更文挑战第19天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
32 3
滚雪球学Java(65):深入理解Java中的Map接口:实现原理剖析
|
3月前
|
存储 缓存 算法
滚雪球学Java(62):HashSet的底层实现原理解析
【6月更文挑战第16天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
32 3
滚雪球学Java(62):HashSet的底层实现原理解析
|
3月前
|
存储 Java 测试技术
滚雪球学Java(61):从源码角度解读Java Set接口底层实现原理
【6月更文挑战第15天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
40 1
滚雪球学Java(61):从源码角度解读Java Set接口底层实现原理
|
2月前
|
存储 安全 Java
(二) 彻底理解Java并发编程之 Synchronized关键字实现原理剖析
Synchronized 关键字(互斥锁)原理,一线大厂不变的面试题,同时也是理解 Java 并发编程必不可少的一环!其中覆盖的知识面很多,需要理解的点也很多,本文会以相关书籍和结合自己的个人理解,从基础的应用范围到底层深入剖析的方式进行阐述,如果错误或疑问欢迎各位看官评论区留言纠正,谢谢!
|
2月前
|
算法 Java
详解 Java 限流接口实现问题之固定窗口限流算法的实现原理是什么
详解 Java 限流接口实现问题之固定窗口限流算法的实现原理是什么