1、foreach循環遍歷對象
foreach循環遍歷對象的時候底層是使用迭代器進行迭代的,即該對象必須直接或者間接的實現了Iterable接口,一般以able結尾代表某種能力,實現了iterable代表給予了實現類迭代的能力。
我們先寫一個List集合然后使用 javac 類名.java 對該.java文件進行編譯成類名.class字節碼文件然后使用 javap -verbose 類名.class 指令進行反編譯查看一下字節碼指令,或者如果用的是Intellij idea的話,里面內置了Fernflower decompiler,直接打開.class文件會直接顯示反編譯后的代碼(記得在查看class文件之前要先執行一下它的java文件)。這里我們使用兩種方式都來試驗一下。
下面是我寫的一個簡單的List集合的對象
1 import java.util.Collections; 2 import java.util.List; 3 4 public class Test { 5 public static void main(String[] args) { 6 List<Integer> list = Collections.emptyList(); 7 for(int a : list){ 8 System.out.println(a); 9 } 10 } 11 12 }
直接使用指令反編譯
這里我是找到我的Test.java文件的地址,拖到桌面上然后執行
javac Test.java
在桌面上生成生成Test.class文件,然后執行
javap -verbose Test.class
就會顯示反編譯后的信息,這里我截取了main方法中的一段
Code: stack=2, locals=4, args_size=1 0: invokestatic #2 // Method java/util/Collections.emptyList:()Ljava/util/List; 3: astore_1 4: aload_1 5: invokeinterface #3, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator; 10: astore_2 11: aload_2 12: invokeinterface #4, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z 17: ifeq 43 20: aload_2 21: invokeinterface #5, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object; 26: checkcast #6 // class java/lang/Integer 29: invokevirtual #7 // Method java/lang/Integer.intValue:()I 32: istore_3 33: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 36: iload_3 37: invokevirtual #9 // Method java/io/PrintStream.println:(I)V 40: goto 11 43: return
根據第5行和第13行判斷出使用了迭代器進行了迭代。
使用Intellij idea直接查看
使用Intellij idea直接查看Test.class文件的話會顯示如下,感覺挺方便的
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package sdu.edu.Test; 7 8 import java.util.Collections; 9 import java.util.Iterator; 10 import java.util.List; 11 12 public class Test { 13 public Test() { 14 } 15 16 public static void main(String[] args) { 17 List<Integer> list = Collections.emptyList(); 18 Iterator var2 = list.iterator(); 19 20 while(var2.hasNext()) { 21 int a = (Integer)var2.next(); 22 System.out.println(a); 23 } 24 25 } 26 }
可以看到直接把foreach轉換成新建了List的迭代器進行迭代。
2、foreach循環遍歷數組
foreach循環遍歷數組的時候將其轉型成為對每一個數組元素的循環引用
還是按照上面同樣的方法來進行查看
Test.java代碼如下
1 public class Test { 2 public static void main(String[] args) { 3 String[] strs= new String[3]; 4 for(String str : strs){ 5 System.out.println(str); 6 } 7 } 8 }
執行上面的指令后反編譯信息如下:
Code: stack=2, locals=6, args_size=1 0: iconst_3 1: anewarray #2 // class java/lang/String 4: astore_1 5: aload_1 6: astore_2 7: aload_2 8: arraylength 9: istore_3 10: iconst_0 11: istore 4 13: iload 4 15: iload_3 16: if_icmpge 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/String;)V 33: iinc 4, 1 36: goto 13 39: return
對字節碼指令不熟悉的我看不出來上面什么意思......
運用Intellij idea查看Test.class文件后如下圖所示
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package sdu.edu.Test; public class Test { public Test() { } public static void main(String[] args) { String[] strs = new String[3]; String[] var2 = strs; int var3 = strs.length; for(int var4 = 0; var4 < var3; ++var4) { String str = var2[var4]; System.out.println(str); } } }
根據Intellij idea來查看還是比較清晰的,foreach轉變成對每一個數組元素的
參考文章:
https://blog.csdn.net/yaomingyang/article/details/80771171