1、foreach循环遍历对象
foreach循环遍历对象的时候底层是使用迭代器进行迭代的,即该对象必须直接或者间接的实现了Iterable接口,一般以able结尾代表某种能力,实现了iterable代表给予了实现类迭代的能力。
我们先写一个List集合然后使用 javac 类名.java 对该.java文件进行编译成类名.class字节码文件然后使用 javap -verbose 类名.class 指令进行反编译查看一下字节码指令,或者如果用的是Intellij idea的话,里面内置了Fernflower decompiler,直接打开.class文件会直接显示反编译后的代码(记得在查看class文件之前要先执行一下它的java文件)。这里我们使用两种方式都来试验一下。
下面是我写的一个简单的List集合的对象
import java.util.Collections;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Integer> list = Collections.emptyList();
for(int a : list){
System.out.println(a);
}
}
}
直接使用指令反编译
这里我是找到我的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文件的话会显示如下,感觉挺方便的
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package sdu.edu.Test;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class Test {
public Test() {
}
public static void main(String[] args) {
List<Integer> list = Collections.emptyList();
Iterator var2 = list.iterator();
while(var2.hasNext()) {
int a = (Integer)var2.next();
System.out.println(a);
}
}
}
可以看到直接把foreach转换成新建了List的迭代器进行迭代。
2、foreach循环遍历数组
foreach循环遍历数组的时候将其转型成为对每一个数组元素的循环引用
还是按照上面同样的方法来进行查看
Test.java代码如下
public class Test {
public static void main(String[] args) {
String[] strs= new String[3];
for(String str : strs){
System.out.println(str);
}
}
}
执行上面的指令后反编译信息如下:
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转变成对每一个数组元素的