Java JDK1.5的新特性之for-each循环的底层原理
今天给大家分享一下for-each 循环的底层原理,故事还得从字节码反汇编和反编译说起...
首先看一下Java JDK1.5 的新特性
- 泛型: ...
- for-each. ...
- 自动拆箱和装箱功能 ...
- 枚举: ...
- 可变参数 ...
- 静态导入 ...
- 线程并发库
对于字节码反汇编,可以使用 JDK 自带的工具 javap
首先看一下 javap 有哪些指令以及用法
$ javap 用法: javap <options> <classes> 其中, 可能的选项包括: -help --help -? 输出此用法消息 -version 版本信息 -v -verbose 输出附加信息 -l 输出行号和本地变量表 -public 仅显示公共类和成员 -protected 显示受保护的/公共类和成员 -package 显示程序包/受保护的/公共类 和成员 (默认) -p -private 显示所有类和成员 -c 对代码进行反汇编 -s 输出内部类型签名 -sysinfo 显示正在处理的类的 系统信息 (路径, 大小, 日期, MD5 散列) -constants 显示最终常量 -classpath <path> 指定查找用户类文件的位置 -cp <path> 指定查找用户类文件的位置 -bootclasspath <path> 覆盖引导类文件的位置
由此可见,在我们拿到字节码文件之后,使用javap -c 字节码文件位置,即可进行反汇编
其实 for-each 是 jdk 1.5 的语法糖,它可以迭代集合和数组
1.for-each 迭代集合
首先来看 for-each 迭代集合
public static void main(String[] args) { List<String> 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."<init>":()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."<init>":()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<String> 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."<init>":()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循环。
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!