短い答え: 場合によります
少し長い 回答: コンパイラ、VM、および VM の設定によって異なります。
背景: サーバー モードで HotSpot VM (最も一般的なフレーバー) を使用すると、VM がサーバー モードで不変ホイストをループするため、両方のバリアントが等しくなります。クライアントモードでは、VM が最適化の価値があると判断した場合、これは実行される場合もあれば、実行されない場合もあり、後で実行される場合もあります。
ループ不変巻き上げはループ最適化の 1 つで、最近のほとんどのコンパイラ (または 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
ご覧のとおり、2 番目の例の 20 行目からの getfield 操作は、最初の例の 1 行目にあり、ループの外側 (バリアント 1 の 7 ~ 39 行目とバリアント 2 の 2 ~ 35 行目) にあるため、実行されるだけです。 1000000 回の代わりに ondced。