4

メモリ使用量と変数のインスタンス化に関して、どちらが優れているか、違いはありません:

これ

for(int i = 0; i < someValue; i++)
{
    Obj foo = new Obj();
    Use foo.....
}

とは対照的に:

Obj foo;

for(int i = 0; i < someValue; i++)
{
    foo = new Obj();
    Use foo.....
}
4

6 に答える 6

11

違いはありません。メモリ使用量に関する潜在的な違いは、コンパイラによって最適化されます。

2つの例を(を使用してjavap -c)コンパイルしてバイトコードを比較すると、バイトコードが同じであることがわかります。もちろん、これはJVMのバージョンによって異なります。しかし、この例は非常に些細なものであるため、どちらももう一方よりもメモリ効率が高いと考えるのはおそらく安全です。


例1:

コード:

public class example1 {
    public static void main(String[] args) {
        for (int i=0; i<10; i++) {
            Object a = new Object();
        }
    }
}

バイトコード:

public class example1 extends java.lang.Object{
public example1();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   bipush  10
   5:   if_icmpge       22
   8:   new     #2; //class java/lang/Object
   11:  dup
   12:  invokespecial   #1; //Method java/lang/Object."<init>":()V
   15:  astore_2
   16:  iinc    1, 1
   19:  goto    2
   22:  return
}

例2:

コード:

public class example2 {
    public static void main(String[] args) {
        Object a;
        for (int i=0; i<10; i++) {
            a = new Object();
        }
    }
}

バイトコード:

public class example2 extends java.lang.Object{
public example2();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_2
   2:   iload_2
   3:   bipush  10
   5:   if_icmpge       22
   8:   new     #2; //class java/lang/Object
   11:  dup
   12:  invokespecial   #1; //Method java/lang/Object."<init>":()V
   15:  astore_1
   16:  iinc    2, 1
   19:  goto    2
   22:  return
}
于 2012-05-26T18:39:49.047 に答える
6

最新のJVMでは、両方が同じように機能します。また、コンパイラの最適化により、両方が同じになります。

コンパイラの最適化と最新のJVMを無視すると、最初のアプローチの方が優れています。

于 2012-05-26T18:40:11.940 に答える
5

最初の例は、オブジェクトスコープの観点から最も理にかなっていますが、どちらももう一方と同じようにメモリ効率が高いはずです。

于 2012-05-26T18:40:31.900 に答える
5

他の回答で指摘されているように、あなたの例に違いはありません。しかし、興味深い質問は次のとおりです。サンプルが遅い場合、どうすればよいでしょうか?

パフォーマンスが非常に重要なセクションでの割り当て/ガベージ コレクションに費やす時間を短縮したい場合は、反復ごとに新しいオブジェクトを割り当てるのではなく、オブジェクトを再利用することを検討してください。

foo = new Obj();
for(int i = 0; i < someValue; i++)
{
    foo.init(i);
    Use foo.....
}

Javaパフォーマンスチューニングから(古い本ですが、現代のjvm:sと.NET clrでも同じことが当てはまります)

... オブジェクトの作成にはコストがかかります。同じオブジェクトを再利用することが妥当な場合は、そうする必要があります。new を呼び出さない場合に注意する必要があります。かなり明白な状況の 1 つは、オブジェクトを既に使用していて、同じクラスの別のオブジェクトを作成する前にそのオブジェクトを破棄できる場合です。オブジェクトを見て、オブジェクトを捨てて別のオブジェクトを作成するのではなく、フィールドをリセットして再利用できるかどうかを検討する必要があります。これは、常に使用および破棄されるオブジェクトにとって特に重要です。

于 2012-05-26T19:40:01.837 に答える
3

コンパイラの最適化により、両方が同じになります。ただし、コンパイラの最適化を無視する場合は、最初のアプローチの方が適しています。それはより要点であり、Joshua Bloch でさえ、Effective Java でそうすることを提案しています (すばらしい読み物です)。

于 2012-06-14T23:34:19.090 に答える
1

コンパイラはこれを最適化する必要があります。読みやすいので、2番目よりも1番目の方が好きです。より広いObject foo範囲を持たせることは混乱の原因となる可能性があります。

于 2012-05-26T21:15:19.953 に答える