第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

lambda 調(diào)用如何與接口交互?

lambda 調(diào)用如何與接口交互?

小怪獸愛吃肉 2024-01-28 16:57:35
下面顯示的代碼片段有效。但是,我不確定它為什么有效。我不太明白 lambda 函數(shù)如何將信息傳遞到接口的邏輯??刂茩?quán)傳遞到哪里了?編譯器如何理解n循環(huán)中的每個和message創(chuàng)建的每個?這段代碼編譯并給出了預(yù)期的結(jié)果。我只是不知道怎么做。import java.util.ArrayList;import java.util.List;public class TesterClass {    public static void main(String[] args) {        List<String> names = new ArrayList<>();        names.add("Akira");        names.add("Jacky");        names.add("Sarah");        names.add("Wolf");        names.forEach((n) -> {            SayHello hello = (message) -> System.out.println("Hello " + message);            hello.speak(n);        });    }    interface SayHello {        void speak(String message);    }}
查看完整描述

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)建一個新實例,這是錯誤的。

查看完整回答
反對 回復(fù) 2024-01-28
?
墨色風(fē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


查看完整回答
反對 回復(fù) 2024-01-28
  • 2 回答
  • 0 關(guān)注
  • 172 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號