gpt4 book ai didi

java - Java中的Lambda表达式机制

转载 作者:行者123 更新时间:2023-12-02 11:57:31 25 4
gpt4 key购买 nike

我刚刚在一本书中读到,当将 lambda 表达式分配给函数式接口(interface)时,就会为 lambda 设置“目标类型”,并使用以下命令创建该类型的实例(即函数式接口(interface)的类型)用作函数接口(interface)中抽象方法实现的 lambda 表达式。

我的问题:如果是这样,那么这是否意味着 lambda 并不是真正独立的方法,也不是引入到语言中的一种新元素类型,而只是简单的一种更紧凑的方式来表达匿名类,因此仅仅在编译器方面添加了设施(就像泛型一样)?

此外,方法引用如何遵守这一点,特别是不与任何对象关联的静态方法?例如,当对实例方法的方法引用分配给功能接口(interface)时,将使用该方法的封装对象,但是在静态方法的情况下会发生什么 - 这些方法不与任何对象关联..? p>

最佳答案

If so, then does that mean lambdas aren't really standalone methods and as such a new type of element brought into the language,

正确,lambda 被编译成具有合成名称的普通方法

but are simply a more compact way for expressing an anonymous class and as such merely are added facility (just like generics) on the compiler's side?

不,这不仅仅是在编译器方面。还有涉及 JVM 中的代码,因此编译器不必为 lambda 编写类文件。

Moreover, how do method references comply with that, in particular, static methods which are not associated with any objects?

方法引用与 lambda 没有什么不同:在运行时必须有一个实现函数接口(interface)的对象。在调用对象的“SAM”时,此方法将调用引用的方法。

For example, when a method reference to an instance method is assigned to a functional interface then the encapsulating object for that method is used,

不,不能使用。让我们以使用 System.out::println 为例:方法引用:

Arrays.asList("A", "B").forEach(System.out::println);

List<E>.forEach()预计 Consumer<? super E>它定义了方法 void accept(E e) 。编译器需要在类文件中生成字节码和其他信息,以便在运行时 JVM 可以生成实现 Consumer<E> 的类。使用方法void accept(E e) 。然后,此生成的方法调用 System.out.println(Object o) .

运行时生成的类看起来像这样

class $$lambda$xy implements Consumer<Object> {
private PrintStream out;

$$lambda$xy(PrintStream out) {
this.out = out;
}

void accept(Object o) {
out.println(o);
}
}
<小时/>

评论中的问题:“为什么不直接分配给实例及其方法?”

让我们稍微扩展一下这个例子:

static void helloWorld(Consumer<String> consumer) {
consumer.apply("Hello World!");
}

public static void main(String[] args) {
helloWorld(System.out::println);
}

要编译它,编译器必须生成字节码来创建实现 Consumer<String> 的对象(因此它可以将对象传递给 helloWorld() )。该对象必须以某种方式存储调用它时的信息 accept(x)它必须调用 println(x) 的方法关于System.out打印流。

其他语言可能对此类对象有其他名称或概念 - 在 Java 中,既定概念是“实现接口(interface)的匿名类和该匿名类的对象”。

对象如何存储这些信息?好吧,你可以发明一些 super 酷的新方法来存储这些信息。 Java 语言设计者认为,就目前而言,匿名类就足够了。但他们有先见之明,如果有人提出一个新想法,以更有效的方式实现它,那么这应该很容易集成到 Java 生态系统(Java 编译器和 JVM)中。

因此,他们还决定不在编译时创建该匿名类,而是让编译器将必要的信息写入类文件中。现在,JVM 可以在运行时决定存储信息的最佳方式(在正确的对象上调用正确的方法)。

关于java - Java中的Lambda表达式机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47484965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com