2 回答

TA貢獻(xiàn)2011條經(jīng)驗 獲得超2個贊
這SayHello
是一個單一抽象方法接口,它有一個接受字符串并返回 void 的方法。這類似于消費者。您只是以使用者的形式提供該方法的實現(xiàn),這類似于以下匿名內(nèi)部類實現(xiàn)。
SayHello?sh?=?new?SayHello()?{ ????@Override ????public?void?speak(String?message)?{ ????????System.out.println("Hello?"?+?message); ????} }; names.forEach(n?->?sh.speak(n));
幸運的是,您的接口有一個方法,以便類型系統(tǒng)(更正式地說,類型解析算法)可以將其類型推斷為SayHello
.?但如果有 2 個或更多方法,這是不可能的。
然而,更好的方法是在 for 循環(huán)之前聲明使用者并使用它,如下所示。聲明每次迭代的實現(xiàn)都會創(chuàng)建不必要的對象,這對我來說似乎違反直覺。這是使用方法引用而不是 lambda 的增強版本。這里使用的有界方法引用調(diào)用上面聲明的實例上的相關(guān)方法hello
。
SayHello?hello?=?message?->?System.out.println("Hello?"?+?message); names.forEach(hello::speak);
更新
考慮到對于無狀態(tài) lambda,僅在創(chuàng)建實例時才不會從其詞法范圍捕獲任何內(nèi)容,這兩種方法都僅創(chuàng)建 的一個實例SayHello
,并且遵循建議的方法沒有任何收益。然而,這似乎是一個實現(xiàn)細(xì)節(jié),直到現(xiàn)在我才知道。因此,更好的方法是將消費者傳遞給您的 forEach,如下面評論中所建議的。另請注意,所有這些方法都僅創(chuàng)建SayHello
界面的一個實例,而最后一種更簡潔。它看起來是這樣的。
names.forEach(message?->?System.out.println("Hello?"?+?message));
以下是 JLS?§15.27.4的相關(guān)部分:Lambda 表達(dá)式的運行時求值
這些規(guī)則旨在為 Java 編程語言的實現(xiàn)提供靈活性,因為:
不需要在每次評估時分配新對象。
事實上,我最初認(rèn)為每次評估都會創(chuàng)建一個新實例,這是錯誤的。

TA貢獻(xiàn)1853條經(jīng)驗 獲得超6個贊
foreach 的簽名如下所示:
void forEach(Consumer<? super T> action)
它接受 Consumer 對象。Consumer 接口是一個函數(shù)式接口(具有單個抽象方法的接口)。它接受輸入并且不返回結(jié)果。
定義如下:
@FunctionalInterface
public interface Consumer {
void accept(T t);
}
因此,任何實現(xiàn),您的情況都可以用兩種方式編寫:
Consumer<String> printConsumer = new Consumer<String>() {
public void accept(String name) {
SayHello hello = (message) -> System.out.println("Hello " + message);
hello.speak(n);
};
};
或者
(n) -> {
SayHello hello = (message) -> System.out.println("Hello " + message);
hello.speak(n);
}
類似地,SayHello 類的代碼可以寫為
SayHello sh = new SayHello() {
@Override
public void speak(String message) {
System.out.println("Hello " + message);
}
};
或者
SayHello hello = message -> System.out.println("Hello " + message);
因此,names.foreach在內(nèi)部首先調(diào)用consumer.accept方法并運行其lambda/匿名實現(xiàn),該實現(xiàn)創(chuàng)建并調(diào)用SayHello lambda實現(xiàn)等等。使用lambda表達(dá)式,代碼非常緊湊、清晰。您唯一需要了解它是如何工作的,即在您的情況下它使用消費者界面。
所以最終流程:foreach -> consumer.accept -> sayhello.speak
添加回答
舉報