java for each 的源_Java JDK1.5的新特性之for-each循环的底层原理

今天给大家分享一下for-each循环的底层原理,故事还得从字节码反汇编和反编译说起...

首先看一下Java JDK1.5的新特性

泛型: ...

for-each. ...

自动拆箱和装箱功能 ...

枚举: ...

可变参数 ...

静态导入 ...

线程并发库

对于字节码反汇编,可以使用 JDK 自带的工具 javap

首先看一下 javap 有哪些指令以及用法

$ javap

用法: javap

其中, 可能的选项包括:

-help --help -? 输出此用法消息

-version 版本信息

-v -verbose 输出附加信息

-l 输出行号和本地变量表

-public 仅显示公共类和成员

-protected 显示受保护的/公共类和成员

-package 显示程序包/受保护的/公共类

和成员 (默认)

-p -private 显示所有类和成员

-c 对代码进行反汇编

-s 输出内部类型签名

-sysinfo 显示正在处理的类的

系统信息 (路径, 大小, 日期, MD5 散列)

-constants 显示最终常量

-classpath 指定查找用户类文件的位置

-cp 指定查找用户类文件的位置

-bootclasspath 覆盖引导类文件的位置

由此可见,在我们拿到字节码文件之后,使用javap -c 字节码文件位置,即可进行反汇编

其实 for-each 是 jdk 1.5 的语法糖,它可以迭代集合和数组

1.for-each 迭代集合

首先来看for-each 迭代集合

public static void main(String[] args) {

List a = new ArrayList<>();

a.add("1");

a.add("2");

a.add("3");

for (String temp : a) {

System.out.print(temp);

}

}

javap 反汇编这段代码

$ javap -c ForeachTest.class

Compiled from "ForeachTest.java"

public class cn.ixan.design.ForeachTest {

public cn.ixan.design.ForeachTest();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: new #2 // class java/util/ArrayList

3: dup

4: invokespecial #3 // Method java/util/ArrayList."":()V

7: astore_1

8: aload_1

9: ldc #4 // String 1

11: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z

16: pop

17: aload_1

18: ldc #6 // String 2

20: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z

25: pop

26: aload_1

27: ldc #7 // String 3

29: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z

34: pop

35: aload_1

36: invokeinterface #8, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;

41: astore_2

42: aload_2

43: invokeinterface #9, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z

48: ifeq 71

51: aload_2

52: invokeinterface #10, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;

57: checkcast #11 // class java/lang/String

60: astore_3

61: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream;

64: aload_3

65: invokevirtual #13 // Method java/io/PrintStream.print:(Ljava/lang/String;)V

68: goto 42

71: return

}

由第 36 行,第 43 行,第 52 行可知,迭代集合使用到了 Iterator

然后使用 idea 查看字节码文件,发现 foreach 遍历集合运用迭代器

public static void main(String[] args) {

List a = new ArrayList();

a.add("1");

a.add("2");

a.add("3");

Iterator var2 = a.iterator();

while(var2.hasNext()) {

String temp = (String)var2.next();

System.out.print(temp);

}

}

2.for-each 迭代数组

我们知道集合继承 Iterable 接口,使用使用 iterator 迭代集合,

那么数组没有继承 Iterable 接口,for-each 是如何迭代它呢?

首先来看 for-each 迭代数组

public static void main(String[] args) {

String[] arr = {"1","2"};

for(String e : arr){

System.out.println(e);

}

}

javap 反汇编这段代码

$ javap -c ForeachTest.class

Compiled from "ForeachTest.java"

public class cn.ixan.design.ForeachTest {

public cn.ixan.design.ForeachTest();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: iconst_2

1: anewarray #2 // class java/lang/String

4: dup

5: iconst_0

6: ldc #3 // String 1

8: aastore

9: dup

10: iconst_1

11: ldc #4 // String 2

13: aastore

14: astore_1

15: aload_1

16: astore_2

17: aload_2

18: arraylength

19: istore_3

20: iconst_0

21: istore 4

23: iload 4

25: iload_3

26: if_icmpge 49

29: aload_2

30: iload 4

32: aaload

33: astore 5

35: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;

38: aload 5

40: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

43: iinc 4, 1

46: goto 23

49: return

}

和迭代集合不同,没有出现 Iterator,说明没有使用迭代器

第 18 行 arraylength,可能使用到了数组的 length 属性

使用 idea 反编译查看,发现 for-each 遍历数组是经典 for 循环

public static void main(String[] args) {

String[] arr = new String[]{"1", "2"};

String[] var2 = arr;

int var3 = arr.length;

for(int var4 = 0; var4 < var3; ++var4) {

String e = var2[var4];

System.out.println(e);

}

}

总结:  1.for-each 迭代集合时,使用的是迭代器迭代集合。

2.for-each 迭代数组时,使用的是经典for循环。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值