关于java:返回这个有什么问题?

What's wrong with returning this?

在我工作的公司,有一份文档描述了我们应该在Java中遵循的良好实践。其中之一是避免返回this的方法,例如:

1
2
3
4
5
6
7
8
class Properties {

  public Properties add(String k, String v) {
   //store (k,v) somewhere
     return this;
  }

}

我会有这样一堂课,所以我能写:

1
 properties.add("name","john").add("role","swd"). ...

我已经多次见过这样的习语,比如在StringBuilder中,并没有发现任何问题。

他们的论证是:

... can be the source of synchronization problems or failed expectations about the states of target objects.

我想不出这可能是真的情况,你们有谁能举个例子吗?

编辑该文档没有指定任何有关可变性的内容,因此我没有看到链接调用和执行以下操作之间的差异:

1
2
properties.add("name","john");
properties.add("role","swd");

我会尝试与发起人联系,但我想用我的枪加载,这就是为什么我发布了这个问题。

解决:我得与其中一位作者交谈,他的初衷显然是为了避免释放尚未准备好的对象,比如在Builder模式中,并解释说如果在调用之间发生上下文切换,则对象可能在无效的状态。我认为这与返回this无关,因为你可能会犯同样的错误购买逐个调用方法,并且更多地与正确地同步构建过程有关。他承认该文件可能更加明确,并将很快修改。胜利是我的/我们的!


我的猜测是他们反对可变状态(通常是正确的)。如果您没有设计返回this的fluent接口,而是返回具有已更改状态的对象的新不可变实例,则可以避免同步问题或没有"failed expectations about the states of target objects"。这可能解释了他们的要求。


这种做法唯一严肃的基础是避免可变对象;批评它"混乱"并导致"失败的期望"是相当薄弱的。一个人不应该在没有熟悉其语义的情况下使用对象,并且为了满足那些选择不再阅读Javadoc的人而强制执行A??PI的约束并不是一个好习惯—特别是因为,正如您所注意到的,返回this以实现流畅的API设计是Java中的标准方法之一,而且确实非常受欢迎。


我认为有时这种方法非常有用,例如在'builder'模式中。

我可以说,在我的组织中,这种事情是由声纳规则控制的,我们没有这样的规则。

另一个猜测是,项目可能是在现有代码库的基础上构建的,这是一种遗留限制。

所以我在这里建议的唯一一件事就是和写这篇文章的人交谈:)

希望这可以帮助


我认为在某些情况下使用该模式是完全可以接受的。

例如,作为Swing开发人员,我经常使用GridBagLayout来发挥它的优势和灵活性,但是任何曾经使用它的人(在犯罪GridBagConstraints中都是它的伙伴)都知道它可能非常冗长且不易阅读。

我在网上看到的一个常见的解决方法(我使用的是)是GridBagConstraints(GBConstraints)的子类,它为每个不同的属性都有一个setter,每个setter返回它。这允许开发人员根据需要链接不同的属性。

生成的代码大小约为1/4,并且对于可能不熟悉使用GridBagConstaints的临时开发人员来说,可读/可维护性更强。