荟萃馆

位置:首页 > 计算机 > java语言

java增强for循环的原理验证

java语言1.91W

在java里,我们是怎么写for循环的代码呢。下面是小编为大家带来的关于java增强for循环的原理验证的知识,欢迎阅读

java增强for循环的原理验证
  java增强for循环的原理验证

第一种:最传统的for循环写法,for(代码段a;代码段b;代码段c),其中代码段a是初次进入for循环时执行的代码,代码段b是一个boolean的表达式,true则继续执行for循环内容,false则停止for循环,代码段c则是在for循环内部执行完后执行。

第二种:针对集合的遍历,for(类型 单个对象:集合对象)。第二种即是增强for循环。

本文的目的就是讲解增强for循环的原理。先看我的测试用例:

jdk版本:1.7.0_51

java 用例代码:

package ;

import ys;

import ator;

import ;

/**

* 增强for循环编译测试

* Created by cd_huang on 2017/4/14.

*/

public class ForeachTest {

public static void superForeachTestArray(){

String[] args =new String[]{"1","2"};

for(String s:args) {

tln(s);

}

}

public static void foreachTestArray(){

String[] args =new String[]{"1","2"};

String[] args2 = args;

int len = th;

for(int i = 0; i < len; ++i) {

String s= args2[i];

tln(s);

}

}

public static void superForeachTestIterator(){

List list = st(new String[]{"1","2"});

for(String s:list) {

tln(s);

}

}

public static void foreachTestIterator(){

List list = st(new String[]{"1","2"});

Iterator it = ator();

while(ext()) {

String s = (String)();

tln(s);

}

}

}

命令行输入:C:Usershcd>javac c:

生成s文件。

命令行输入:C:Usershcd>javap -v c:s

生成java编译后的字节码指令。

Classfile /c:/s

Last modified 2017-4-14; size 1307 bytes

MD5 checksum 5296942b41a468b4fa1f88e3123db02f

Compiled from ""

public class achTest

SourceFile: ""

minor version: 0

major version: 51

flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

#1 = Methodref #13.#28 // java/lang/Object."":()V

#2 = Class #29 // java/lang/String

#3 = String #30 // 1

#4 = String #31 // 2

#5 = Fieldref #32.#33 // java/lang/:Ljava/io/PrintStream;

#6 = Methodref #34.#35 // java/io/tln:(Ljava/lang/String;)V

#7 = Methodref #36.#37 // java/util/st:([Ljava/lang/Object;)Ljava/util/List;

#8 = InterfaceMethodref #38.#39 // java/util/ator:()Ljava/util/Iterator;

#9 = InterfaceMethodref #40.#41 // java/util/ext:()Z

#10 = InterfaceMethodref #40.#42 // java/util/:()Ljava/lang/Object;

#11 = InterfaceMethodref #38.#39 // java/util/ator:()Ljava/util/Iterator;

#12 = Class #43 // com/onlyou/olyfinance/supply/web/ForeachTest

#13 = Class #44 // java/lang/Object

#14 = Utf8

#15 = Utf8 ()V

#16 = Utf8 Code

#17 = Utf8 LineNumberTable

#18 = Utf8 superForeachTestArray

#19 = Utf8 StackMapTable

#20 = Class #45 // "[Ljava/lang/String;"

#21 = Utf8 foreachTestArray

#22 = Utf8 superForeachTestIterator

#23 = Class #46 // java/util/List

#24 = Class #47 // java/util/Iterator

#25 = Utf8 foreachTestIterator

#26 = Utf8 SourceFile

#27 = Utf8

#28 = NameAndType #14:#15 // "":()V

#29 = Utf8 java/lang/String

#30 = Utf8 1

#31 = Utf8 2

#32 = Class #48 // java/lang/System

#33 = NameAndType #49:#50 // out:Ljava/io/PrintStream;

#34 = Class #51 // java/io/PrintStream

#35 = NameAndType #52:#53 // println:(Ljava/lang/String;)V

#36 = Class #54 // java/util/Arrays

#37 = NameAndType #55:#56 // asList:([Ljava/lang/Object;)Ljava/util/List;

#38 = Class #46 // java/util/List

#39 = NameAndType #57:#58 // iterator:()Ljava/util/Iterator;

#40 = Class #47 // java/util/Iterator

#41 = NameAndType #59:#60 // hasNext:()Z

#42 = NameAndType #61:#62 // next:()Ljava/lang/Object;

#43 = Utf8 com/onlyou/olyfinance/supply/web/ForeachTest

#44 = Utf8 java/lang/Object

#45 = Utf8 [Ljava/lang/String;

#46 = Utf8 java/util/List

#47 = Utf8 java/util/Iterator

#48 = Utf8 java/lang/System

#49 = Utf8 out

#50 = Utf8 Ljava/io/PrintStream;

#51 = Utf8 java/io/PrintStream

#52 = Utf8 println

#53 = Utf8 (Ljava/lang/String;)V

#54 = Utf8 java/util/Arrays

#55 = Utf8 asList

#56 = Utf8 ([Ljava/lang/Object;)Ljava/util/List;

#57 = Utf8 iterator

#58 = Utf8 ()Ljava/util/Iterator;

#59 = Utf8 hasNext

#60 = Utf8 ()Z

#61 = Utf8 next

#62 = Utf8 ()Ljava/lang/Object;

{

public achTest();

flags: ACC_PUBLIC

Code:

stack=1, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

LineNumberTable:

line 11: 0

public static void superForeachTestArray();

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=4, locals=5, args_size=0

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_0

15: aload_0

16: astore_1

17: aload_1

18: arraylength

19: istore_2

20: iconst_0

21: istore_3

22: iload_3

23: iload_2

24: if_icmpge 46

27: aload_1

28: iload_3

29: aaload

30: astore 4

32: getstatic #5 // Field java/lang/:Ljava/io/PrintStream;

35: aload 4

37: invokevirtual #6 // Method java/io/tln:(Ljava/lang/String;)V

40: iinc 3, 1

43: goto 22

46: return

LineNumberTable:

line 14: 0

line 15: 15

line 16: 32

line 15: 40

line 18: 46

StackMapTable: number_of_entries = 2

frame_type = 255 /* full_frame */

offset_delta = 22

locals = [ class "[Ljava/lang/String;", class "[Ljava/lang/String;", int, int ]

stack = []

frame_type = 248 /* chop */

offset_delta = 23

public static void foreachTestArray();

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=4, locals=5, args_size=0

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_0

15: aload_0

16: astore_1

17: aload_0

18: arraylength

19: istore_2

20: iconst_0

21: istore_3

22: iload_3

23: iload_2

24: if_icmpge 46

27: aload_1

28: iload_3

29: aaload

30: astore 4

32: getstatic #5 // Field java/lang/:Ljava/io/PrintStream;

35: aload 4

37: invokevirtual #6 // Method java/io/tln:(Ljava/lang/String;)V

40: iinc 3, 1

43: goto 22

46: return

LineNumberTable:

line 21: 0

line 22: 15

line 23: 17

line 24: 20

line 25: 27

line 26: 32

line 24: 40

line 28: 46

StackMapTable: number_of_entries = 2

frame_type = 255 /* full_frame */

offset_delta = 22

locals = [ class "[Ljava/lang/String;", class "[Ljava/lang/String;", int, int ]

stack = []

frame_type = 250 /* chop */

offset_delta = 23

public static void superForeachTestIterator();

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=4, locals=3, args_size=0

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: invokestatic #7 // Method java/util/st:([Ljava/lang/Object;)Ljava/util/List;

17: astore_0

18: aload_0

19: invokeinterface #8, 1 // InterfaceMethod java/util/ator:()Ljava/util/Iterator;

24: astore_1

25: aload_1

26: invokeinterface #9, 1 // InterfaceMethod java/util/ext:()Z

31: ifeq 54

34: aload_1

35: invokeinterface #10, 1 // InterfaceMethod java/util/:()Ljava/lang/Object;

40: checkcast #2 // class java/lang/String

43: astore_2

44: getstatic #5 // Field java/lang/:Ljava/io/PrintStream;

47: aload_2

48: invokevirtual #6 // Method java/io/tln:(Ljava/lang/String;)V

51: goto 25

54: return

LineNumberTable:

line 31: 0

line 32: 18

line 33: 44

line 34: 51

line 35: 54

StackMapTable: number_of_entries = 2

frame_type = 253 /* append */

offset_delta = 25

locals = [ class java/util/List, class java/util/Iterator ]

frame_type = 250 /* chop */

offset_delta = 28

public static void foreachTestIterator();

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=4, locals=3, args_size=0

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: invokestatic #7 // Method java/util/st:([Ljava/lang/Object;)Ljava/util/List;

17: astore_0

18: aload_0

19: invokeinterface #11, 1 // InterfaceMethod java/util/ator:()Ljava/util/Iterator;

24: astore_1

25: aload_1

26: invokeinterface #9, 1 // InterfaceMethod java/util/ext:()Z

31: ifeq 54

34: aload_1

35: invokeinterface #10, 1 // InterfaceMethod java/util/:()Ljava/lang/Object;

40: checkcast #2 // class java/lang/String

43: astore_2

44: getstatic #5 // Field java/lang/:Ljava/io/PrintStream;

47: aload_2

48: invokevirtual #6 // Method java/io/tln:(Ljava/lang/String;)V

51: goto 25

54: return

LineNumberTable:

line 38: 0

line 39: 18

line 40: 25

line 41: 34

line 42: 44

line 43: 51

line 44: 54

StackMapTable: number_of_entries = 2

frame_type = 253 /* append */

offset_delta = 25

locals = [ class java/util/List, class java/util/Iterator ]

frame_type = 28 /* same */

}

上面的是java代码编译过后的二进制指令。不过单单看这个肯定是不够的。需要对java的运行时内存模型有一定的了解,明白栈帧,操作数栈,局部变量表,常量池这些东西的'概念,才能理解在执行这些指令时,对应的东西里会产生什么变化。当然,要理解我说的增强for循环原理,并不需要看懂这些指令。认真观察上面的二进制指令,superForeachTestArray()方法编译后的指令,即第86行到121行,和foreachTestArray() 方法编译后的指令,即第137行到172行,两个方法编译后的指令是一样的。

superForeachTestIterator()方法编译后的指令,即第191行到222行,和foreachTestIterator() 方法编译后的指令,即第237行到268行,两个方法编译后的指令是一样的。

这说明什么问题?说明了增强for循环是一个编译前的概念,在编译后编译器会对代码进行优化。有两种对象支持增强for循环:一种是数组,编译器对数组的优化只是写法上的优化,即superForeachTestArray()方法内的增强for循环在编译后会变成foreachTestArray() 方法里for循环的代码。一种是实现了Iterable接口的对象,对于这种,其实质是拿到对象的迭代器进行遍历,即superForeachTestIterator()方法内的增强for循环在编译后会变成foreachTestIterator() 方法内的迭代器遍历。迭代器遍历的好处是安全,且它是对遍历的一种抽象,有种解耦的意味在里面。

标签:JAVA 验证