创建一个新对象并返回它,还是在返回语句中创建新对象更好?

8
例如:
public Person newPerson() {
  Person p = new Person("Bob", "Smith", 1112223333);
  return p;
}

相对于:

public Person newPerson() {
  return new Person("Bob", "Smith", 1112223333);
}

另一种方法是否更有效?
6个回答

20

就性能而言,两种方式并没有什么区别。

  • 就调试而言,建议使用前一种方式——也就是当您需要跟踪执行过程、在创建和返回之间记录一些信息时使用。
  • 从可读性的角度来看(但这是主观的),后一种方式更好。

通常来说,我建议选择后一种方式,并且每当您需要调试时,暂时切换到第一种(两行)方式。


1
我认为两者的可读性都不会比另一个更好,那么为什么要进行临时切换呢?JIT编译器为任何一种模式生成的代码可能完全相同。没有区别。因此,如果第一个模式有任何优势,无论多么微小,为什么不只是使用它(或者至少在进行更改后保留它)? - Michael Burr
3
对我而言,直接返回结果更易读。但在使用调试器进行跟踪时,将其分成两行会更方便。并可能在其中记录调试信息。 - Bozho
3
这句话的意思是,问题在于你是在优化可读性还是可调试性。有人可能会认为代码被阅读(由人类)的次数远远超过了它被调试的次数。 - Steve Kuo
因为它更易读,所以这是一种权衡,而不是明显的优势。这就是工程学。 - benzado

11

在返回之前,将赋值操作赋给一个临时变量可以让您有机会在newPerson()内部进行错误检查和纠正。 返回新的函数调用需要newPerson()方法的调用者捕获并从错误中恢复。


3
如果正在进行对该变量的进一步访问,则不会有问题,因为该情况不再存在。 - Robin
1
实际上,在代码审查中,我会质疑这种方法的存在。一个一行的new*()例程返回一个带有一些默认值的Person?如果你不打算在newPerson()例程中提供一些额外的功能来覆盖"new Person()"调用,那么在我看来,newPerson()是一个具有有限用处的方法。为什么不直接使用:public Person() {...}构造函数?同样的事情,没有方法调用层。它们都是同样糟糕的方法选择,但至少第一种形式给了你一个机会去为用户做一些有用的事情,他们自己调用new Person()时得不到。 - Ian C.
这个例子中的方法很简单。我更喜欢使用简单的例子,而不是发布我在实际代码中使用的方法。 - mheathershaw
1
即使那是代码(目前它很琐碎),工厂方法是有效的设计模式的原因在于,它们的实现可能会发生巨大变化。newPerson不需要返回一个新对象(可以返回子类),而构造函数必须返回一个新的Person实例,这与Java的面向接口的设计背道而驰。 - ehdv

1

没有哪一个比另一个更有效率,JIT会在运行时将其内联到最有效率的方式。


1
在一个理智的世界里,它们将编译成完全相同的字节码,因此就性能而言它们是相同的。唯一的区别在于人类:
创建一个临时变量会使调试稍微容易一些:你可以在返回语句上设置断点并检查p的值。在单行版本中,这样做更加困难。
一行完成的方式消除了一个变量,减少了复杂性,使代码稍微容易阅读一些。
实际上,我会用一行写出来,如果遇到调试问题,最坏的情况下我会创建一个临时变量。此外,单元测试不是应该消除对调试的需求吗? :-)

0

其中一个并不比另一个更有效,但是直接返回已创建的对象可能更加干净,因为您使用了较少的临时变量。如果必须使用临时变量,请将其设置为 final 并适当命名。


请澄清临时变量的位置。我一直认为P被实例化并返回对P的引用。如果您没有声明P,则仍会实例化对象并传递引用。 - Keith Adler
1
Java通过值传递变量,它会复制P并在返回时使P超出范围。 - user177800
就像@fuzzy所说的那样。一个好的编译器可以优化实现,但就源代码而言,“p”是一个临时变量。这就是它被称为的原因。一直以来都是这样,将来也会是这样。 - polygenelubricants

0
第二个选项更短,更易于阅读。
虽然我怀疑任何像样的Java编译器都不会为第一个选项创建效率低下的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接