让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 Spec不兼容。

有很多规范依赖于这些标准访问器。

你总能让它们共存。

public class Some {
    public String getValue() { // JavaBeans
        return value;
    }
    public void setValue(final String value) { // JavaBeans
        this.value = value;
    }
    public String value() { // simple
        return getValue();
    }
    public Some value(final String value) { // fluent/chaining
        setValue(value);
        return this;
    }
    private String value;
}

现在我们可以一起用了。

new Some().value("some").getValue();

下面是另一个版本的不可变对象。

public class Some {

    public static class Builder {

        public Some build() { return new Some(value); }

        public Builder value(final String value) {
            this.value = value;
            return this;
        }

        private String value;
    }

    private Some(final String value) {
        super();
        this.value = value;
    }

    public String getValue() { return value; }

    public String value() { return getValue();}

    private final String value;
}

现在我们可以这么做了。

new Some.Builder().value("value").build().getValue();

其他回答

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

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

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

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

如果在整个应用程序中使用相同的约定,则似乎没有问题。

另一方面,如果应用程序的现有部分使用标准约定,我会坚持下去,并向更复杂的类添加构建器

public class NutritionalFacts {
    private final int sodium;
    private final int fat;
    private final int carbo;

    public int getSodium(){
        return sodium;
    }

    public int getfat(){
        return fat;
    }

    public int getCarbo(){
        return carbo;
    }

    public static class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder sodium(int s) {
            this.sodium = s;
            return this;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

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

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

这可能可读性较差

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);