增强for循环与普通for循环相比,功能更强并且代码更简洁
写一段代码:
@Test public void test_foreach() { List<String> list = new ArrayList<String>(); list.add("1111"); list.add("2222"); for (String str : list) { System.out.println(str); } }
其实我之前用jdk6时,直接在class文件就可以看到,foreach已经转化成迭代器Iterator实现,jdk8貌似不行,只能看编译后字节码文件,javap -c Test.class:
public void test_foreach(); Code: 0: new #46 // class java/util/ArrayList 3: dup 4: invokespecial #47 // Method java/util/ArrayList."<init >":()V 7: astore_1 8: aload_1 9: ldc #48 // String 1111 11: invokeinterface #49, 2 // InterfaceMethod java/util/List.ad d:(Ljava/lang/Object;)Z 16: pop 17: aload_1 18: ldc #50 // String 2222 20: invokeinterface #49, 2 // InterfaceMethod java/util/List.ad d:(Ljava/lang/Object;)Z 25: pop 26: aload_1 27: invokeinterface #51, 1 // InterfaceMethod java/util/List.it erator:()Ljava/util/Iterator; 32: astore_2 33: aload_2 34: invokeinterface #52, 1 // InterfaceMethod java/util/Iterato r.hasNext:()Z 39: ifeq 62 42: aload_2 43: invokeinterface #53, 1 // InterfaceMethod java/util/Iterato r.next:()Ljava/lang/Object; 48: checkcast #40 // class java/lang/String 51: astore_3 52: getstatic #12 // Field java/lang/System.out:Ljava/ io/PrintStream; 55: aload_3 56: invokevirtual #14 // Method java/io/PrintStream.printl n:(Ljava/lang/String;)V 59: goto 33 62: return
new、dup、invokespecial这些字节码指令表内定义的指令,用来执行指定c++代码,我们看不懂没关系,先暂不关注。但是我们可以看到 List.iterator(),Iterator.hasNext()这些信息,这表示foreach底层是通过迭代器实现的,实现迭代器的条件是要实现迭代器接口Iterator,很显然List继承Collection接口,Collection接口又继承Iterator接口。
但是数组也是可以使用foreach循环,但它却没有继承迭代器Iterator接口,这是怎么回事?
@Test public void test_foreach_arr() { String[] ss = {"111","222"}; for (String str : ss) { System.out.println(str); } }
看下字节码文件:
public void test_foreach_arr(); Code: 0: iconst_2 1: anewarray #40 // class java/lang/String 4: dup 5: iconst_0 6: ldc #41 // String 111 8: aastore 9: dup 10: iconst_1 11: ldc #42 // String 222 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 #12 // Field java/lang/System.out:Ljava/ io/PrintStream; 38: aload 5 40: invokevirtual #14 // Method java/io/PrintStream.printl n:(Ljava/lang/String;)V 43: iinc 4, 1 46: goto 23 49: return
其实说真的这个字节码我真看不懂,网上有人说看goto语句,貌似数组的foreach循环实际用的还是for循环,那我们写个for循环比对下它俩字节码。
数组for循环实现:
@Test public void test_for() { String[] ss = {"111", "222"}; for (int i = 0; i < ss.length; i++) { System.out.println(ss[i]); } }
字节码文件:
public void test_for(); Code: 0: iconst_2 1: anewarray #40 // class java/lang/String 4: dup 5: iconst_0 6: ldc #41 // String 111 8: aastore 9: dup 10: iconst_1 11: ldc #42 // String 222 13: aastore 14: astore_1 15: iconst_0 16: istore_2 17: iload_2 18: aload_1 19: arraylength 20: if_icmpge 38 23: getstatic #12 // Field java/lang/System.out:Ljava/ io/PrintStream; 26: aload_1 27: iload_2 28: aaload 29: invokevirtual #14 // Method java/io/PrintStream.printl n:(Ljava/lang/String;)V 32: iinc 2, 1 35: goto 17 38: return
比对发现,其实数组的foreach循环和for循环运行是一致的,再回头看字节码中有个arraylength,基本可以联想到,最终数组foreach也是通过数组的长度来进行遍历。
时间: 2024-10-13 07:33:26