简短的回答:这取决于
稍长 答案:这取决于编译器、VM 和 VM 的设置。
背景:在服务器模式下使用 HotSpot VM(最常见的风格)将使两种变体相等,因为 VM 在服务器模式下会循环不变提升。在客户端模式下,如果 VM 认为值得优化,这可能会完成,可能不会完成,甚至可以稍后完成。
循环不变提升是循环优化之一,它在大多数现代编译器(或者在 Java 的情况下,VM)中实现。至于 javac 生成的代码:如果 VM 没有进一步优化,您的第一个代码片段将执行得更快。
public static boolean check(Test$MyObject, java.util.List);
Code:
0: aload_0
1: getfield #7; //Field Test$MyObject.p:I
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: ldc #4; //int 1000000
10: if_icmpge 42
13: aload_1
14: iload_3
15: invokeinterface #11, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
20: checkcast #5; //class Test$MyObject
23: astore 4
25: aload 4
27: getfield #7; //Field Test$MyObject.p:I
30: iload_2
31: if_icmpge 36
34: iconst_0
35: ireturn
36: iinc 3, 1
39: goto 7
42: iconst_1
43: ireturn
--
public static boolean check(Test$MyObject, java.util.List);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: ldc #4; //int 1000000
5: if_icmpge 38
8: aload_1
9: iload_2
10: invokeinterface #11, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
15: checkcast #5; //class Test$MyObject
18: astore_3
19: aload_3
20: getfield #7; //Field Test$MyObject.p:I
23: aload_0
24: getfield #7; //Field Test$MyObject.p:I
27: if_icmpge 32
30: iconst_0
31: ireturn
32: iinc 2, 1
35: goto 2
38: iconst_1
39: ireturn
如您所见,第二个示例中第 20 行的 getfield 操作位于第一个示例中的第 1 行,并且位于循环之外(变体 1 中的第 7 到 39 行和变体 2 中的第 2 到 35 行),因此仅执行ondced 而不是 1000000 次。