让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类。


当前回答

我同意所有声称这破坏了JavaBeans规范的帖子。有理由保留这一点,但我也觉得使用这个构建器模式(上面提到的)有它的一席之地;只要不是到处都用,就应该是可以接受的。对我来说,“It’s Place”的终点是对“build()”方法的调用。

There are other ways of setting all these things of course, but the advantage here is that it avoids 1) many-parameter public constructors and 2) partially-specified objects. Here, you have the builder collect what's needed and then call its "build()" at the end, which can then ensure that a partially-specified object is not constructed, since that operation can be given less-than-public visibility. The alternative would be "parameter objects", but that IMHO just pushes the problem back one level.

我不喜欢多形参构造函数,因为它们更有可能传入大量相同类型的实参,从而更容易将错误的实参传递给形参。我不喜欢使用大量的setter,因为对象可以在完全配置之前使用。此外,使用“build()”方法更好地实现基于先前选择的默认值的概念。

总之,我认为这是一个很好的实践,如果使用得当。

其他回答

这种特殊的模式称为方法链接。维基百科的链接,这有更多的解释和例子,如何在各种编程语言中完成。

附注:只是想把它留在这里,因为我正在寻找具体的名字。

坏习惯: setter集 getter get

如果显式地声明一个方法,为U

setPropertyFromParams(array $hashParamList) { ... }

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

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

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

如果你不想从setter返回'this',但又不想使用第二个选项,你可以使用下面的语法来设置属性:

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

顺便说一句,我认为它在c#中略干净:

list.Add(new Employee() {
    Name = "Jack Sparrow",
    Id = 1,
    Foo = "bacon!"
});

我过去更喜欢这种方法,但我已经决定不这么做了。

原因:

可读性。将每个setFoo()放在单独的行上可以使代码更具可读性。通常情况下,您阅读代码的次数要比编写代码的次数多得多。 副作用:setFoo()应该只设置字段foo,没有其他。返回this是一个额外的“WHAT was that”。

我看到的Builder模式没有使用setFoo(foo). setbar (bar)约定,而是使用了更多的foo(foo).bar(bar)。也许正是出于这些原因。

这总是一个品味问题。我只是喜欢“最少惊喜”的方法。