Java中foreach循环两种实现原理

一、foreach循环Iterator模式
  • 首先我们看一个foreach循环的main方法
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class Test {

    public static void main(String[] args) {
        List<String> list = Collections.emptyList();

        for(String s:list) {
            System.out.println("aaa..."+s);
        }
        System.out.println("end...");
    }
}
  • 使用java -verbose命令对Test类的字节码文件反编译
C:\Program Files\Java\jdk1.7.0_45\bin>javap -verbose C:\software\develop\workpla
ce\ggindex\tmp\classes\ggindex\v2\stock\action\Test.class

我截取了反编译后输出的一段指令:

         0: invokestatic  #16                 // Method java/util/Collections.emtyList:()Ljava/util/List;
         3: astore_1
         4: aload_1
         5: invokeinterface #22,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
        10: astore_3
        11: goto          46
        14: aload_3
        15: invokeinterface #28,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        20: checkcast     #34                 // class java/lang/String
        23: astore_2
        24: getstatic     #36                 // Field java/lang/System.out:Ljava/io/PrintStream;
        27: new           #42                 // class java/lang/StringBuilder
        30: dup
        31: ldc           #44                 // String aaa...
        33: invokespecial #46                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
        36: aload_2
        37: invokevirtual #49                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        40: invokevirtual #53                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        43: invokevirtual #57                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        46: aload_3
        47: invokeinterface #62,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
        52: ifne          14
        55: getstatic     #36                 // Field java/lang/System.out:Ljava/io/PrintStream;
        58: ldc           #66                 // String end...
        60: invokevirtual #57                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        63: return

上面的指令都是jvm中的字节码指令,我们只需要看懂如下几行就可以,可以看到第五行的指令展示了java/util/List.iterator:()Ljava/util/Iterator;第15行的指令展示调用了java/util/Iterator.next:(),第47行指令展示调用了java/util/Iterator.hasNext:();这几行的输出就可以完全的说明foreach循环将对List数组的遍历转换成了Iterator目标迭代器的方式遍历。

  • List之所以能够使用foreach循环,List的所有实现类都是Collection接口的子类,而Collection又是Iterator接口的子类;List的实现类继承了一个AbstractList抽象类,这个抽象类完全实现了Iterator迭代器。
  • 任何的一个集合,无论是JDK提供的还是自己实现的要想使用foreach循环必须实现Iterator迭代器。
  • 只要是Collection的子类都可以使用foreach循环,前提是要实现了Iterator迭代器。
二、foreach循环引用模式
  • 如下面的java数组类
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class Test {

    public static void main(String[] args) {
        String[] str = {"a","b"};

        for(String s:str) {
            System.out.println("aaa..."+s);
        }
        System.out.println("end...");
    }
}
  • 使用java -verbose命令反编译字节码文件
C:\Program Files\Java\jdk1.7.0_45\bin>javap -verbose C:\software\develop\workpla
ce\ggindex\tmp\classes\ggindex\v2\stock\action\Test.class
  • 编译的结果是:
         0: iconst_2
         1: anewarray     #16                 // class java/lang/String
         4: dup
         5: iconst_0
         6: ldc           #18                 // String a
         8: aastore
         9: dup
        10: iconst_1
        11: ldc           #20                 // String b
        13: aastore
        14: astore_1
        15: aload_1
        16: dup
        17: astore        5
        19: arraylength
        20: istore        4
        22: iconst_0
        23: istore_3
        24: goto          57
        27: aload         5
        29: iload_3
        30: aaload
        31: astore_2
        32: getstatic     #22                 // Field java/lang/System.out:La/io/PrintStream;
        35: new           #28                 // class java/lang/StringBuilde
        38: dup
        39: ldc           #30                 // String aaa...
        41: invokespecial #32                 // Method java/lang/StringBuild"<init>":(Ljava/lang/String;)V
        44: aload_2
        45: invokevirtual #35                 // Method java/lang/StringBuildappend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        48: invokevirtual #39                 // Method java/lang/StringBuildtoString:()Ljava/lang/String;
        51: invokevirtual #43                 // Method java/io/PrintStream.ptln:(Ljava/lang/String;)V
        54: iinc          3, 1
        57: iload_3
        58: iload         4
        60: if_icmplt     27
        63: getstatic     #22                 // Field java/lang/System.out:La/io/PrintStream;
        66: ldc           #48                 // String end...
        68: invokevirtual #43                 // Method java/io/PrintStream.ptln:(Ljava/lang/String;)V
        71: return

通过上面的指令集我们可以推测foreach循环将普通的数组转换成了for(int i=0;i<4;i++)的引用模式来遍历数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值