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


当前回答

我制作setter已经有一段时间了,唯一真正的问题是库坚持使用严格的getPropertyDescriptors来获得bean读取器/写入器bean访问器。在这些情况下,您的java“bean”将没有您所期望的写入器。

例如,我还没有测试它的确定,但我不会感到惊讶,杰克逊不会识别这些设置时,从json/maps创建java对象。我希望我在这一点上是错的(我很快就会测试它)。

事实上,我正在开发一个轻量级的以SQL为中心的ORM,我必须在getPropertyDescriptors之外添加一些代码来识别返回此的设置器。

其他回答

Paulo Abrantes提供了另一种使JavaBean setter流畅的方法:为每个JavaBean定义一个内部构建器类。如果您正在使用的工具被返回值的setter弄得不知所措,Paulo的模式可能会有所帮助。

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

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

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

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

我不认为这有什么特别的问题,这只是风格的问题。它在以下情况下很有用:

您需要一次设置多个字段(包括在构建时) 您知道在编写代码时需要设置哪些字段 对于想要设置的字段,有许多不同的组合。

这种方法的替代方法可能是:

一个mega构造函数(缺点:你可能会传递很多空值或默认值,并且很难知道哪个值对应什么) 几个重载的构造函数(缺点:一旦你有多个构造函数,就会变得笨拙) 工厂方法/静态方法(缺点:与重载构造函数相同——一旦超过几个就会变得笨拙)

如果你一次只设置几个属性,我会说不值得返回this。如果您稍后决定返回其他内容,例如状态/成功指示符/消息,那么它肯定会崩溃。

这不是坏习惯。这是一种越来越普遍的做法。大多数语言不需要你处理返回的对象,如果你不想这样做,所以它不会改变“正常”setter使用语法,但允许你将setter链接在一起。

这通常被称为构建器模式或流畅接口。

它在Java API中也很常见:

String s = new StringBuilder().append("testing ").append(1)
  .append(" 2 ").append(3).toString();