lambda调用如何与接口交互?

问题描述 投票:4回答:1

下面显示的代码段有效。但是,我不确定为什么会起作用。我不太了解lambda函数如何将信息传递到接口的逻辑。

控制权在哪里传递?编译器如何理解循环中的每个n和创建的每个message

此代码编译并给出预期的结果。我只是不确定如何。

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);
    }
}
java lambda java-8 interface
1个回答
4
投票

sayHello是一个Single Abstract方法接口,该接口具有一个接受字符串并返回void的方法。这类似于消费者。您只是以使用者的形式提供该方法的实现,类似于下面的匿名内部类实现。

sayHello sh = new sayHello() {
    @Override
    public void speak(String message) {
        System.out.println("Hello " + message);
    }
};

names.forEach(n -> sh.speak(n));

幸运的是,您的接口只有一个方法,以便类型系统(更正式地讲,类型解析算法)可以将其类型推断为sayHello。但是,如果要使用2种或更多的方法,那将是不可能的。

但是,更好的方法是在for循环之前声明使用者,并按如下所示使用它。声明每次迭代的实现会创建更多对象,这对我来说似乎是违反直觉的。这是使用方法引用而不是lambda的增强版本。此处使用的有界方法引用在上面声明的hello实例上调用相关方法。

sayHello hello = message -> System.out.println("Hello " + message);
names.forEach(hello::speak);
© www.soinside.com 2019 - 2024. All rights reserved.