Java 7中的链式调用?

时间:2009-06-18 10:14:06

标签: java language-design language-features java-7

我刚刚阅读Java 7 preview presentation (pdf)并且链式调用上有一张幻灯片。以下是幻灯片中使用的示例:

// 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世界来到Java。在Delphi中有with语言结构。这是少数人所珍惜和许多人的厌恶(或者是相反的方式?)。我发现with比链式调用的想法更优雅(我相信它是基于void方法返回对它被调用的对象的引用 - 这是我不喜欢的部分不喜欢,因为void应该返回 nothing )。

我很欣赏Java采用的with语言功能,因此示例代码可以像这样编写:

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

我是唯一一个更喜欢这种链式调用解决方案的人吗?其他人认为with可能是Java语言的有用扩展吗? (让我想起有人对“Java ++”的需求的问题......)

6 个答案:

答案 0 :(得分:13)

with 语句可以使用带有初始化程序的匿名类在Java中进行翻译:

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

使用这个习语的缺点是有充分记录here

链式调用是Method Chaining的别名。这是众所周知的习语,适用于任何版本的Java:

class Chained {

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

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

JDK 7的提案是allowing of chaining method also for void return type

class ChainedJava7 {

    public void withFoo() { 
        // ...
    }

    public void withBar() { 
        // ...
    }
}    

答案 1 :(得分:2)

This可能会让您感兴趣。

答案 2 :(得分:2)

我非常喜欢该表单的with语句,但我更喜欢它们的VB版本:

With testObject
    .Height = 100
    .Text = "Hello, World"
    .ForeColor = System.Drawing.Color.Green
End With

由于With块中的每个属性仍然必须以.开头,因此您知道您正在引用Object属性而不是局部变量,从而减少了任何命名空间冲突。

如果我们举个例子:

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

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

答案 3 :(得分:1)

我不喜欢使用with;我更喜欢Python with statement。我同意你的意见void应该是void。在您提供的示例中,如果一个人真的希望能够链接方法调用,那么他们应该只更改其方法的返回类型,以便它们可以链接。

答案 4 :(得分:1)

也许对一个对象的许多调用是一些代码需要移动的标志?

答案 5 :(得分:1)

Effective Java项目#2中的Joshua Bloch强烈建议在拥有大量参数的构造函数时使用Builder。一个原因是可以编写它以保证构建的对象始终处于一致状态。它还避免在构建对象的类中具有复杂的“伸缩构造函数”。还有一个是如果你想让构建的对象不可变(例如,为了线程安全),它就不能有setter方法。