Java7中的链式调用?

Java7中的链式调用?,java,language-design,language-features,java-7,Java,Language Design,Language Features,Java 7,我正在读一篇文章,里面有一张关于链式调用的幻灯片。以下是幻灯片中使用的示例: // Construction with setters DrinkBuilder margarita = new DrinkBuilder(); margarita.add("tequila"); margarita.add("orange liqueur"); margarita.add("lime juice"); margarita.withRocks(); margarita.withSalt(); Drin

我正在读一篇文章,里面有一张关于链式调用的幻灯片。以下是幻灯片中使用的示例:

// Construction with setters
DrinkBuilder margarita = new DrinkBuilder();
margarita.add("tequila");
margarita.add("orange liqueur");
margarita.add("lime juice");
margarita.withRocks();
margarita.withSalt();
Drink drink = margarita.drink();

// Construction with chained invocation
Drink margarita = new DrinkBuilder()
    .add("tequila")
    .add("orange liqueur")
    .add("lime juice")
    .withRocks()
    .withSalt()
    .drink();
对此我有复杂的感觉。不应该将太多的方法调用链接到一个语句中。另一方面,写
margarita.this()
margarita.that()
也不太方便

现在,我从Delphi world来到Java。在Delphi中有语言结构。这是少数人所珍视的,也是许多人所厌恶的(或者是反过来呢?)。我发现
with
比链式调用的思想更优雅(我相信链式调用是基于
void
方法返回调用对象的引用而起作用的,这是我不喜欢的部分,因为
void
应该不返回任何内容)

我希望Java采用
语言特性,因此示例代码可以这样编写:

Drink margarita = null;
with (new DrinkBuilder()) {
    add("tequila");
    add("orange liqueur");
    add("lime juice");
    withRocks();
    withSalt();
    margarita = drink();
}

我是唯一一个喜欢这个解决方案而不是链式调用的人吗?还有人认为
with
是Java语言的有用扩展吗?(让我想起了有人提出的关于“Java++”需求的问题……)

我不喜欢使用
with
;我更喜欢这个。不过,我同意你所说的
void
应该是
void
。在您提供的示例中,如果一个人真的希望能够链接方法调用,他们只需更改方法上的返回类型,使其可链接。

您可能会感兴趣。

可以使用带有初始值设定项的匿名类在Java中翻译with语句:

Drink margarita = new DrinkBuilder() {{
    add(“tequila”);
    add(“orange liqueur”);
    add(“lime juice”);
    withRocks();
    withSalt();
}}.drink();
使用这个习惯用法的缺点已经有了很好的记录

链接调用是方法链接的别名。这是众所周知的习惯用法,适用于任何版本的Java:

class Chained {

    public Chained withFoo() { 
        // ...
        return this;
    }

    public Chained withBar() { 
        // ...
        return this;
    }
}    
JDK 7的提案是:


我非常喜欢那种形式的
语句,但我更喜欢它们的VB版本:

With testObject
    .Height = 100
    .Text = "Hello, World"
    .ForeColor = System.Drawing.Color.Green
End With
由于
With
块中的每个属性前面仍然必须有一个
,因此您知道您引用的是对象属性,而不是局部变量,从而减少了任何名称空间冲突

如果我们以你为例:

with (new DrinkBuilder()) {
    add(“tequila”);
    add(“orange liqueur”);
    add(“lime juice”);
    withRocks();
    withSalt();
    margarita = drink();
}

很难判断
withSalt()
DrinkBuilder
的方法还是本地类中的方法。如果在
with
块中只允许
with
-ed对象的方法,那么我认为它们会变得不那么有用。

可能对一个对象的多次调用表明需要移动一些代码?

Joshua Bloch在第2项中强烈建议,当您有一个具有大量代码的构造函数时,使用生成器论据。一个原因是,可以编写它来保证构建对象始终处于一致状态。它还避免了在构建对象的类中使用复杂的“伸缩构造函数”。还有一点是,如果您希望构建的对象是不可变的(例如,为了线程安全),那么它不能有setter方法。

这不仅限于Java 7,您可以通过在方法中简单地返回“This”来编写生成器。一个很好的例子是java.lang.StringBuilder。我想重点是java 7允许链接而不返回此值,因此更改了方法调用的语义。我刚刚在写双括号初始化时,您的答案出现了:-)注意,几个月前,对JDK7进行小的语言更改的截止日期已经过去了。我的建议是使用alt()作为饮料生成器的一种方法。如果发现应用程序没有执行它应该执行的操作,可以调用this.withSalt();要使其显式化,应该调用哪个对象的withSalt()方法。嗯,它是void。作为生产者,你不想退货,你的消费者也不想收到任何东西(尽管有时他们会这样做)。你为什么要在乎?从语义上讲,没有什么变化(除了必须输入这么多),除了返回一些东西,并且隐式地执行它。如果没有返回任何内容,则无法对其调用方法。因为这是Java,而且几乎所有其他内容都是显式的,所以我希望返回是显式的。不,这是整个Bean咒语的一部分,因为Java没有第一类属性,所以我们必须为所有内容编写getter和setter。这就是为什么。从Java7(属性)中删除的其他内容。@darthcoder-很高兴您提到这一点!我不明白为什么从1.0开始这就不是Java的一部分
with (new DrinkBuilder()) {
    add(“tequila”);
    add(“orange liqueur”);
    add(“lime juice”);
    withRocks();
    withSalt();
    margarita = drink();
}