java for each 的源_Java JDK1.5的新特性之for-each循环的底层原理
今天給大家分享一下for-each循環(huán)的底層原理,故事還得從字節(jié)碼反匯編和反編譯說起...
首先看一下Java JDK1.5的新特性
泛型: ...
for-each. ...
自動(dòng)拆箱和裝箱功能 ...
枚舉: ...
可變參數(shù) ...
靜態(tài)導(dǎo)入 ...
線程并發(fā)庫
對(duì)于字節(jié)碼反匯編,可以使用 JDK 自帶的工具 javap
首先看一下 javap 有哪些指令以及用法
$ javap
用法: javap
其中, 可能的選項(xiàng)包括:
-help --help -? 輸出此用法消息
-version 版本信息
-v -verbose 輸出附加信息
-l 輸出行號(hào)和本地變量表
-public 僅顯示公共類和成員
-protected 顯示受保護(hù)的/公共類和成員
-package 顯示程序包/受保護(hù)的/公共類
和成員 (默認(rèn))
-p -private 顯示所有類和成員
-c 對(duì)代碼進(jìn)行反匯編
-s 輸出內(nèi)部類型簽名
-sysinfo 顯示正在處理的類的
系統(tǒng)信息 (路徑, 大小, 日期, MD5 散列)
-constants 顯示最終常量
-classpath 指定查找用戶類文件的位置
-cp 指定查找用戶類文件的位置
-bootclasspath 覆蓋引導(dǎo)類文件的位置
由此可見,在我們拿到字節(jié)碼文件之后,使用javap -c 字節(jié)碼文件位置,即可進(jìn)行反匯編
其實(shí) for-each 是 jdk 1.5 的語法糖,它可以迭代集合和數(shù)組
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 查看字節(jié)碼文件,發(fā)現(xiàn) foreach 遍歷集合運(yùn)用迭代器
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 迭代數(shù)組
我們知道集合繼承 Iterable 接口,使用使用 iterator 迭代集合,
那么數(shù)組沒有繼承 Iterable 接口,for-each 是如何迭代它呢?
首先來看 for-each 迭代數(shù)組
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
}
和迭代集合不同,沒有出現(xiàn) Iterator,說明沒有使用迭代器
第 18 行 arraylength,可能使用到了數(shù)組的 length 屬性
使用 idea 反編譯查看,發(fā)現(xiàn) for-each 遍歷數(shù)組是經(jīng)典 for 循環(huán)
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);
}
}
總結(jié):? 1.for-each 迭代集合時(shí),使用的是迭代器迭代集合。
2.for-each 迭代數(shù)組時(shí),使用的是經(jīng)典for循環(huán)。
總結(jié)
以上是生活随笔為你收集整理的java for each 的源_Java JDK1.5的新特性之for-each循环的底层原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java code viewer_Jav
- 下一篇: java美元兑换,(Java实现) 美元