直面底层之字节码看for循环高级语法糖

988 阅读2分钟

前言

本文从字节码层面看java 高级for循环的语法糖,用字节码分析,揭开高级for循环的面纱。

主要是调用 for(Object o : List) 或者 for(Object o: Object[] )


一、java for(Object o:Object[])

我们写一个简单的代码并 看下字节码:

//java 代码
public static void main(String[] args) {
        Object [] numbers = new Object[]{};
       for(Object i:numbers){
           System.out.println(i);
       }
    }

//字节码
public static void main(java.lang.String[]);
    Code:
       //生成一个长度为0 的数组,放入 局部变量表第一个位置
       0: iconst_0
       1: anewarray     #2  // class java/lang/Object
       4: astore_1
         
       // 将数组引用复制一份 放入局部变量表第二个位置,并计算数组长度放入局部变量表第三个位置
       5: aload_1
       6: astore_2
       7: aload_2
       8: arraylength
       9: istore_3     //存放数组长度
         
       //将0 加载到栈顶,这个代表索引,即我们常说的 i 并存入局部变量表第四个位置
      10: iconst_0
      11: istore        4
      //加载 i 及数组长度 作比较
      13: iload         4   //加载索引值 i
      15: iload_3           //加载数组长度 
      16: if_icmpge     39  //如果i >= 数组长度跳转至39行,否则向下执行
      19: aload_2           //加载数组到栈顶
      20: iload         4   //加载索引到栈顶
      22: aaload            //加载数组中某个索引的值
      23: astore        5   //数组中某个索引的对象存入局部变量表
      25: getstatic     #3   // Field java/lang/System.out:Ljava/io/PrintStream;
      28: aload         5     
      30: invokevirtual #4   // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      33: iinc          4, 1 //将索引值+1 
      36: goto          13   //跳转至13行继续执行
      39: return
}

我们可以看到,数组的for循环for(Object o : Object[]),底层采用的是 for(int i,i < length;i++)的实现形式,前面的高级形式只是Java的语法糖


二、java for(Object o: List)

代码依然很简单

//java
public static void main(String[] args) {
    List<Object> list = new ArrayList<>();
   for(Object o:list){
       System.out.println(o);
   }
}

//字节码
public static void main(java.lang.String[]);
    Code:
       //生成一个list,存入局部变量表第一个位置
       0: new           #2   // class java/util/ArrayList
       3: dup
       4: invokespecial #3   // Method java/util/ArrayList."<init>":()V
       7: astore_1
       
       // 获得list的 iterator 放入局部变量表的 第二个位置
       8: aload_1
       9: invokeinterface #4,  1  // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      14: astore_2
        
      //加载 Iterator 并执行 hasNext,如果没有 则跳转至41行,有则继续往下执行
      15: aload_2
      16: invokeinterface #5,  1  // InterfaceMethod java/util/Iterator.hasNext:()Z
      21: ifeq          41  
      //根据 Iterator.next 获取object 并输出,之后跳转至 15行继续循环
      24: aload_2
      25: invokeinterface #6,  1  // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      30: astore_3
      31: getstatic     #7   // Field java/lang/System.out:Ljava/io/PrintStream;
      34: aload_3
      35: invokevirtual #8  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      38: goto          15
      41: return

我们可以看到,list的for循环for(Object o : List),底层采用的list的 iterator 的实现形式