私は長い間、これと同じ質問をしました。そこで、さらに簡単なコードをテストしました。
結論:このような場合、パフォーマンスに違いはありません。
外ループケース
int intermediateResult;
for(int i=0; i < 1000; i++){
intermediateResult = i+2;
System.out.println(intermediateResult);
}
ループケースの内側
for(int i=0; i < 1000; i++){
int intermediateResult = i+2;
System.out.println(intermediateResult);
}
IntelliJの逆コンパイラでコンパイルされたファイルを確認しましたが、どちらの場合も同じです Test.class
for(int i = 0; i < 1000; ++i) {
int intermediateResult = i + 2;
System.out.println(intermediateResult);
}
また、この回答で示した方法を使用して、両方のケースのコードを逆アセンブルしました。回答に関連する部分のみを表示します
外ループケース
Code:
stack=2, locals=3, args_size=1
0: iconst_0
1: istore_2
2: iload_2
3: sipush 1000
6: if_icmpge 26
9: iload_2
10: iconst_2
11: iadd
12: istore_1
13: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_1
17: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
20: iinc 2, 1
23: goto 2
26: return
LocalVariableTable:
Start Length Slot Name Signature
13 13 1 intermediateResult I
2 24 2 i I
0 27 0 args [Ljava/lang/String;
ループケースの内側
Code:
stack=2, locals=3, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: sipush 1000
6: if_icmpge 26
9: iload_1
10: iconst_2
11: iadd
12: istore_2
13: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_2
17: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
20: iinc 1, 1
23: goto 2
26: return
LocalVariableTable:
Start Length Slot Name Signature
13 7 2 intermediateResult I
2 24 1 i I
0 27 0 args [Ljava/lang/String;
あなたは細心の注意を払う場合は、のみSlot
に割り当てられたi
とintermediateResult
してLocalVariableTable
出現した順番の積としてスワップされます。スロットの同じ違いは、他のコード行にも反映されています。
- 追加の操作は実行されていません
intermediateResult
どちらの場合もまだローカル変数なので、アクセス時間に違いはありません。
ボーナス
コンパイラーは大量の最適化を行います。この場合に何が起こるかを見てください。
ゼロの作業ケース
for(int i=0; i < 1000; i++){
int intermediateResult = i;
System.out.println(intermediateResult);
}
ゼロ作業逆コンパイル
for(int i = 0; i < 1000; ++i) {
System.out.println(i);
}