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


当前回答

这可能可读性较差

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

其他回答

因为它不返回void,所以它不再是一个有效的JavaBean属性setter。如果您是世界上使用可视化“Bean Builder”工具的7个人之一,或者是使用JSP-bean-setProperty元素的17个人之一,那么这可能很重要。

我支持setter使用"this"返回。我不在乎它是否与豆子兼容。对我来说,如果有“=”表达式/语句是可以的,那么返回值的setter是可以的。

这一点也不坏。但是它与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();

总结:

它被称为“流畅接口”或“方法链接”。 这不是“标准”Java,尽管你现在看到的越来越多(在jQuery中工作得很好) 它违反了JavaBean规范,因此它将与各种工具和库分开,特别是JSP构建器和Spring。 它可能会阻止JVM通常会做的一些优化 一些人认为它能清理代码,另一些人认为它“可怕”

还有一些没有提到的要点:

This violates the principal that each function should do one (and only one) thing. You may or may not believe in this, but in Java I believe it works well. IDEs aren't going to generate these for you (by default). I finally, here's a real-world data point. I have had problems using a library built like this. Hibernate's query builder is an example of this in an existing library. Since Query's set* methods are returning queries, it's impossible to tell just by looking at the signature how to use it. For example: Query setWhatever(String what); It introduces an ambiguity: does the method modify the current object (your pattern) or, perhaps Query is really immutable (a very popular and valuable pattern), and the method is returning a new one. It just makes the library harder to use, and many programmers don't exploit this feature. If setters were setters, it would be clearer how to use it.

从声明中

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

我看到两件事

1)毫无意义的话。 2)缺乏可读性。