web-dev-qa-db-ja.com

Javaのループの内部または外部で変数を宣言すると、違いがありますか?

可能性のある複製:
変数はどこで宣言しますか?メソッドの上部またはいつ必要ですか?

Javaのループの内部または外部で変数を宣言すると、違いがありますか?

これは

for(int i = 0; i < 1000; i++) {
   int temp = doSomething();
   someMethod(temp);
}

これと等しい(メモリ使用量に関して)?

int temp = 0;
for(int i = 0; i < 1000; i++) {
   temp = doSomething();
   someMethod(temp);
}

また、一時変数がたとえばArrayListの場合はどうなるでしょうか。

for(int i = 0; i < 1000; i++) {
   ArrayList<Integer> array = new ArrayList<Integer>();
   fillArray(array);
   // do something with the array
}

編集:javap -c次の出力が得られました

ループ外の変数:

  public static void main(Java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iconst_0      
       3: istore_2      
       4: iload_2       
       5: sipush        1000
       8: if_icmpge     25
      11: invokestatic  #2                  // Method doSomething:()I
      14: istore_1      
      15: iload_1       
      16: invokestatic  #3                  // Method someMethod:(I)V
      19: iinc          2, 1
      22: goto          4
      25: return  

ループ内の変数:

  public static void main(Java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     23
       9: invokestatic  #2                  // Method doSomething:()I
      12: istore_2      
      13: iload_2       
      14: invokestatic  #3                  // Method someMethod:(I)V
      17: iinc          1, 1
      20: goto          2
      23: return        

そして興味のある人のために、このコード:

public class Test3 {
    public static void main(String[] args) {
        for(int i = 0; i< 1000; i++) {
            someMethod(doSomething());
        }   
    }
    private static int doSomething() {
        return 1;
    }
    private static void someMethod(int temp) {
        temp++;
    }
}

これを生成します:

  public static void main(Java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     21
       9: invokestatic  #2                  // Method doSomething:()I
      12: invokestatic  #3                  // Method someMethod:(I)V
      15: iinc          1, 1
      18: goto          2
      21: return   

しかし、最適化は実行時に行われます。最適化されたコードを確認する方法はありますか? (長い編集のため申し訳ありません)

13
Puckl

これらの質問のほとんどに対する一般的な答えは、「なぜそれを試してみて、調べてみませんか?」です。 Javaでは、生成されたバイトコード(ツールはjavapと呼ばれると思います)を見て、変数を宣言する2つの方法のバイトコードの違いを確認できます。

次回最適化の問題が発生したときに同じツールを使用して、コンパイラーが期待どおりに動作していることを確認できるため、このようにすることで学習体験が向上します。これにより、コーディングの不必要な変更を回避できます。オプティマイザがそれ自体でうまく機能するときのスタイル、またはパフォーマンスの最後のビットが本当に必要なときに実際の調整を見つけるとき.

4

短い答え:いいえ。このサイトのどこかにすでに同様の質問がありました。生成されたバイトコードごとに顕著な違いはありません。必要に応じて宣言すると、生成されるコード行が少なくなります。

ここに受け入れられた答えがあります: https://softwareengineering.stackexchange.com/a/56590/43451

3
Kemoda

個々の変数のレベルでは、効率に大きな違いはありませんが、1000のループと1000の変数を含む関数がある場合(暗黙の悪いスタイルを気にしないでください)、すべての変数のすべての寿命が続くため、体系的な違いがある可能性があります。オーバーラップする代わりに同じ。これは、スタックサイズや、必要以上に長く保持されていた変数をクリーンアップするガベージコレクターの機能などに影響を与える可能性があります。

また、変数に可能な最小のスコープを与える方がはるかに優れたスタイルです。事故を防ぎます。

1
ddyer