转 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的。

目录
相关文章
|
4月前
|
存储 算法 Java
【Java集合类面试八】、 介绍一下HashMap底层的实现原理
HashMap基于hash算法,通过put和get方法存储和获取对象,自动调整容量,并在碰撞时用链表或红黑树组织元素以优化性能。
|
22天前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
|
3月前
|
存储 缓存 Java
java线程内存模型底层实现原理
java线程内存模型底层实现原理
java线程内存模型底层实现原理
|
4月前
|
安全 Java UED
Java线程池的实现原理及其在业务中的最佳实践
本文讲述了Java线程池的实现原理和源码分析以及线程池在业务中的最佳实践。
|
4月前
|
存储 Java 索引
Java中foreach遍历数组如何拿到想要的值
总结来说,通过foreach循环遍历数组并获取所需的值是一种简单且代码清晰的操作,特别适用于只需访问集合或数组中的每个元素且不需要元素索引或修改集合的场景。在实际编程中,根据场景需求合理选择循环类型,可大大提高代码的可读性与效率。
207 4
|
4月前
|
存储 安全 Java
解锁Java并发编程奥秘:深入剖析Synchronized关键字的同步机制与实现原理,让多线程安全如磐石般稳固!
【8月更文挑战第4天】Java并发编程中,Synchronized关键字是确保多线程环境下数据一致性与线程安全的基础机制。它可通过修饰实例方法、静态方法或代码块来控制对共享资源的独占访问。Synchronized基于Java对象头中的监视器锁实现,通过MonitorEnter/MonitorExit指令管理锁的获取与释放。示例展示了如何使用Synchronized修饰方法以实现线程间的同步,避免数据竞争。掌握其原理对编写高效安全的多线程程序极为关键。
71 1
|
5月前
|
Java 开发者
Java实现基于清除后分配规则的垃圾回收器及其实现原理
通过上述简化模型的实现,我们可以理解基于清除后分配规则的垃圾回收器的基本工作原理。实际上,现代JVM中的垃圾回收器比这个例子复杂得多,它们可能包括更多阶段、优化策略,以及不同类型的垃圾回收器协同工作。然而,理解这一基本概念对于深入理解垃圾回收机制和内存管理非常有帮助。
27 3
|
6月前
|
存储 算法 Java
滚雪球学Java(65):深入理解Java中的Map接口:实现原理剖析
【6月更文挑战第19天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
55 3
|
6月前
|
存储 缓存 算法
滚雪球学Java(62):HashSet的底层实现原理解析
【6月更文挑战第16天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
50 3
|
6月前
|
存储 Java 测试技术
滚雪球学Java(61):从源码角度解读Java Set接口底层实现原理
【6月更文挑战第15天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
72 1