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

没有区别。编译器将优化内存使用方面的任何潜在差异。

如果您编译(使用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。一个相当明显的情况是当您已经使用了一个对象并且可以在您即将创建同一类的另一个对象之前将其丢弃。您应该查看对象并考虑是否可以重置字段然后重用该对象,而不是丢弃它并创建另一个。这对于经常使用和丢弃的对象尤其重要

于 2012-05-26T19:40:01.837 回答
3

The compiler optimization will make both of them same. I prefer the first approach better, however, if you were to ignore the compiler optimization. It is more to the point and even Joshua Bloch suggests to do so in Effective Java (a great read).

于 2012-06-14T23:34:19.090 回答
1

编译器应该为您优化它。我更喜欢第一个而不是第二个,因为它更具可读性。让Object foo范围更大可能会造成混乱。

于 2012-05-26T21:15:19.953 回答