methods valid - 方法鏈接Java




javadoc tag (6)

你真的在問德米特定律

“只跟你的直接朋友說話”

請注意,上面的鏈接是一個很好的資源,但你可以花很長時間在那裡,但沒有得到你想要的答案! :-)

雖然我早些時候回答了一些問題,但最近我一直在做的一些工作中,我一直在想為什麼Java不支持對其內置類進行方法鏈接。

例如,如果我要創建一個Car類,我可以通過重新限製而不是void來使其可鏈接 ,如下所示:

public class Car {
    private String make;        

    public Car setMake(String make) {
        this.make = make;
        return this;
    }   
}

內置庫不傾向於以這種方式做事有什麼特別的原因嗎? 方法鍊是否存在缺點?

我可能忽略了一些可以解釋缺少方法鏈接的東西,但是默認情況下返回void的任何setter方法應該返回對此的引用(至少在我看來應該如此)。 這將使以下情況變得更加清潔。

container.add((new JLabel("label text")).setMaximumSize(new Dimension(100,200)));

而不是更長時間的囉嗦: 注意:如果你願意,它不會阻止你以這種方式編碼。

JLabel label = new JLabel("label text");
label.setMaximumSize(new Dimension(100,200));
container.add(label);

我非常有興趣聽到這個決定背後的原因,如果我不得不猜測會有與此相關的開銷,所以只應在需要時使用。


雖然我們可以猜測真正的原因,但其中一個可能是嚴格來說它不是非常OO。

如果將方法視為表示建模世界的操作的操作,則方法鏈接並不真正適合該圖片。

另一個原因可能是當你試圖覆蓋鍊式方法時可能出現的混亂。 想像一下這種情況:

class Foo {
   Foo chainedMethod() {...}
}

class Bar extends Foo {
   Foo chainedMethod() {...} //had to return Foo for Java versions < 1.5
   void doStuff();
}

因此,當您嘗試執行new Bar().chainedMethod().doStuff() ,它將無法編譯。 和((Bar)new Bar().chainedMethod()).doStuff()看起來不太好,是((Bar)new Bar().chainedMethod()).doStuff() :)


方法鏈通常與Builder模式一起使用,您可以在StringBuilder類中看到它。 除此之外,方法鏈接可以使命令和創建分離不那麼清晰,例如repaint()也應該是流暢的接口的一部分嗎? 然後我可以:

container.add(label).repaint().setMaximumSize(new Dimension(100,200)));

突然,我的調用順序變得很重要,可以隱藏在鏈接方法中。


我能想到的另一個原因是性能 ,或者更確切地說:不要為你不使用的東西買單。 在每個方法都不是很昂貴之後return this ,但仍然需要很少的額外CPU週期和一個CPU註冊表。

甚至有一個想法是向每個聲明void返回值的方法添加隱式return this ,但它被拒絕了。


呃。 可以在兩個方向上進行可讀性論證 - 這就是試圖將過多的東西放在一條線上。

但老實說,我懷疑這是出於歷史原因:當Swing正在開發時,普遍的“鏈接”行為並沒有真正變得流行或眾所周知。 您可能會爭辯說它應該在以後添加,但是這樣的事情往往會產生二進制不兼容性以及Sun / Oracle歷來非常謹慎的其他問題。

更新的JDK庫 - 參見例如ByteBuffer的一個主要的,著名的例子 - 已經提供了鏈接行為等,它是有意義的。


最後總是運行這是整點,只是因為它在返回後出現在代碼中並不意味著它是如何實現的。 退出try塊時,Java運行時負責運行此代碼。

例如,如果您有以下內容:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

運行時將生成如下內容:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

如果拋出未捕獲的異常,則finally塊將運行,異常將繼續傳播。





java methods chaining method-chaining