Javaのループの内側または外側で変数を宣言すると、違いが生じますか?[閉まっている]


13

可能な重複:
どこで変数を宣言しますか?メソッドのトップまたはそれが必要なとき?

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   

ただし、最適化は実行時に行われます。最適化されたコードを見る方法はありますか?(長い編集はごめんなさい)


1
実際に分解を見ていただき、それが何かを教えてくれたことを嬉しく思います。実際のJavaの経験がある人が最適化されたコードに関する最終的な質問に答えてくれることを期待していましたが、おそらくその特定の部分をStackoverflowに投稿することができます-それは非常に具体的な質問のようです。
ジョリスティマーマンズ

はい、最適化されたコードを取得しようとします。(質問は少し変更された、私は編集で最適化されたコードで事を尋ねた)
-Puckl

複製のリンクが壊れています。この質問をオリジナルにする時が来ました。
ゾン

回答:


4

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

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


3

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

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


ループ内で新しいオブジェクトを作成するときのパフォーマンスはどうですか?それは一度だけ作成することもできますか?
バブルラップ

3
この場合、明らかにパフォーマンスとメモリのペナルティがあります。しかし、それはopの質問には当てはまりません
Kemoda

1
リンクが壊れています。
ゾン

1

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

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


これは正しくありません。JVMレベルでは、ローカル変数のスコープが制限されているなどということはありません。
マイケルボルグワード

for(int i = ..)1000回書くと、関数を終了するときにスタック上に1000個の異なる変数があることを意味しますか?
-ddyer

artima.com/insidejvm/ed2/jvm8.htmlによると 、例えば、Example3bのiおよびjローカル変数のように、2つのローカル変数がオーバーラップしない限定されたスコープを持つ場合、コンパイラーは同じ配列エントリを自由に使用できます両方の変数に対して。」そして、それは理にかなっているだけで、コンパイラはこの方法でスタックフレームのサイズを最適化することは自由です。
ddyer

1
いい視点ね; しかし、コンパイラーの最適化について話している場合、コンパイラーは、重複する字句スコープを持つが重複する方法で使用されない変数のローカル変数エントリーをほぼ同じように簡単に再利用できます。
マイケルボルグ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.