2

我很想知道这两个 Java 方法调用中的任何一个在处理器时间、内存分配和/或垃圾收集方面的行为是否完全不同。

SomeObject myObj = new SomeObject();
myObj.doSomething();

对比

new SomeObject().doSomething();
4

7 回答 7

5

查看生成的字节码:

// code 1
new SomeObject().doSomething();

// bytecode 1
   0:   new #2; //class SomeObject
   3:   dup
   4:   invokespecial   #3; //Method SomeObject."<init>":()V
   7:   invokevirtual   #4; //Method SomeObject.doSomething:()V
   10:  return

你可以清楚地看到这个还有两个指令:

// code 2
SomeObject myObj = new SomeObject();
myObj.doSomething();

// bytecode 2
   0:   new #2; //class SomeObject
   3:   dup
   4:   invokespecial   #3; //Method SomeObject."<init>":()V
   7:   astore_1
   8:   aload_1
   9:   invokevirtual   #4; //Method SomeObject.doSomething:()V
   12:  return

这些指令看起来非常多余且易于优化。我敢打赌 JIT 编译器会在需要时处理它们。

于 2010-07-29T20:46:17.183 回答
4

区别恰好是 2 个 JVM 字节码,它转换为 1 个额外的机器指令,JIT 可能会优化掉这些指令(如果您不对变量做任何其他事情)。

于 2010-07-29T20:35:51.517 回答
2

不。    

于 2010-07-29T20:33:10.780 回答
1

假设 myObj 没有用于其他任何事情,正如我从您的问题的性质推断的那样,您应该看不出有什么区别。无论哪种方式,您唯一应该担心这样的开销的情况是,如果该代码处于某个循环中,并且一遍又一遍地执行它,令人作呕。如果是这种情况,Java 的 JIT 优化应该会很好地照顾您,您应该看不出有什么区别。我更喜欢按照第二个示例的方式编写此代码,但这只是我。

于 2010-07-29T20:33:49.873 回答
1

虽然生成的字节码可能不同,但我认为这应该是 jit 编译器更容易优化的事情之一。根据它的实际作用,甚至可以完全优化对象创建。

于 2010-07-29T20:38:13.800 回答
0

两者之间的唯一区别是,只要myObj不清除引用并且具有已path to root分配对象的对象的一部分将不会被垃圾回收。

于 2010-07-29T20:34:35.520 回答
0

第一个示例的效率会稍低一些。在第一个示例中,对象引用将一直保留到函数或封闭块结束。在第二个示例中,一旦调用完成,对象引用将可用于垃圾回收。当然,它实际上可能不是垃圾收集的。

我还没有检查生成的字节码。Java 持有引用的方式可能有所不同,但无论哪种情况,我都怀疑它是微不足道的。

于 2010-07-29T20:48:04.430 回答