我很想知道这两个 Java 方法调用中的任何一个在处理器时间、内存分配和/或垃圾收集方面的行为是否完全不同。
SomeObject myObj = new SomeObject();
myObj.doSomething();
对比
new SomeObject().doSomething();
我很想知道这两个 Java 方法调用中的任何一个在处理器时间、内存分配和/或垃圾收集方面的行为是否完全不同。
SomeObject myObj = new SomeObject();
myObj.doSomething();
对比
new SomeObject().doSomething();
查看生成的字节码:
// 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 编译器会在需要时处理它们。
区别恰好是 2 个 JVM 字节码,它转换为 1 个额外的机器指令,JIT 可能会优化掉这些指令(如果您不对变量做任何其他事情)。
不。
假设 myObj 没有用于其他任何事情,正如我从您的问题的性质推断的那样,您应该看不出有什么区别。无论哪种方式,您唯一应该担心这样的开销的情况是,如果该代码处于某个循环中,并且一遍又一遍地执行它,令人作呕。如果是这种情况,Java 的 JIT 优化应该会很好地照顾您,您应该看不出有什么区别。我更喜欢按照第二个示例的方式编写此代码,但这只是我。
虽然生成的字节码可能不同,但我认为这应该是 jit 编译器更容易优化的事情之一。根据它的实际作用,甚至可以完全优化对象创建。
两者之间的唯一区别是,只要myObj
不清除引用并且具有已path to root
分配对象的对象的一部分将不会被垃圾回收。
第一个示例的效率会稍低一些。在第一个示例中,对象引用将一直保留到函数或封闭块结束。在第二个示例中,一旦调用完成,对象引用将可用于垃圾回收。当然,它实际上可能不是垃圾收集的。
我还没有检查生成的字节码。Java 持有引用的方式可能有所不同,但无论哪种情况,我都怀疑它是微不足道的。