让java中的setter返回“this”是好还是坏?

public Employee setName(String name){
   this.name = name;
   return this;
}

这个模式很有用,因为你可以像这样设置链:

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

而不是这样:

Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);

...但这有点违背标准惯例。我认为这是值得的因为它可以让setter做一些其他有用的事情。我曾在一些地方看到过这种模式(例如JMock、JPA),但它似乎并不常见,而且通常只用于定义良好的api,在这些api中这种模式随处可见。

更新:

我所描述的显然是有效的,但我真正想要的是一些关于这是否被普遍接受的想法,以及是否存在任何陷阱或相关的最佳实践。我知道Builder模式,但它比我所描述的要复杂一些——正如Josh Bloch所描述的,有一个用于对象创建的相关静态Builder类。


当前回答

如果可用,最好使用其他语言结构。例如,在Kotlin中,您可以使用with、apply或let。如果使用这种方法,实际上不需要从setter返回实例。

这种方法允许你的客户端代码:

对返回类型漠不关心 更容易维护 避免编译器的副作用

这里有一些例子。

val employee = Employee().apply {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
with(employee) {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
employee.let {
   it.name = "Jack Sparrow"
   it.id = 1
   it.foo = "bacon"
}

其他回答

这个方案(双关语),称为“流畅界面”,现在变得非常流行。还可以接受,但不是我的菜。

至少在理论上,它会通过在调用之间设置错误的依赖关系而破坏JVM的优化机制。

它被认为是语法糖,但实际上会在超级智能的Java 43虚拟机中产生副作用。

这就是为什么我投反对票,不要使用它。

这可能可读性较差

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!")); 

或者这个

list.add(new Employee()
          .setName("Jack Sparrow")
          .setId(1)
          .setFoo("bacon!")); 

这比:

Employee employee = new Employee();
employee.setName("Jack Sparrow")
employee.setId(1)
employee.setFoo("bacon!")); 
list.add(employee); 

第一眼看到:“可怕!”

进一步思考

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

实际上更不容易出错

Employee anEmployee = new Employee();
anEmployee.setName("xxx");
...
list.add(anEmployee);

非常有趣。添加想法toolbag…

如果我正在编写一个API,我使用“return this”来设置只会设置一次的值。如果我有任何其他值,用户应该能够改变,我使用标准的void setter代替。

然而,在我看来,这真的是一个偏好问题,链式设置器看起来确实很酷。