Java 8 lambdas 是否被编译为内部类、方法或其他东西? [英] Are Java 8 lambdas compiled as inner classes, methods or something else?

查看:16
本文介绍了Java 8 lambdas 是否被编译为内部类、方法或其他东西?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天阅读了这篇关于 lambdas 的文章:

I have read this article today regarding lambdas:

http://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood

文章建议,lambda 没有实现为匿名内部类(由于性能).它给出了一个示例,可以将 lambda 表达式编译为类的(静态)方法.

The article suggests, that lambdas are not implemented as anon inner classes (due to performance). It gives an example that a lambda expression can be compiled as a (static) method of class.

我尝试了一个非常简单的片段:

I have tried a very simple snippet:

private void run() {
    System.out.println(this);
    giveHello(System.out::println);
}

private void giveHello(Consumer<String> consumer) {
    System.out.println(consumer);
    consumer.accept("hello");
}

输出是:

sample.Main@14ae5a5
sample.Main$$Lambda$1/168423058@4a574795
hello

所以这不是同一个实例.它也不是某个中心的Lambda 工厂"实例..

So it's not the same instance. It's not some central "Lambda Factory" instance either..

那么如何实现 lambda 表达式?

How are lambdas implemented then?

推荐答案

假设您传递的是实际的 lambda 表达式 而不是方法引用,则表达式本身被编译为一个单独的合成方法.除了预期功能接口的任何形式参数(例如,在 Consumer 的情况下,单个 String),它将包括任何捕获值的参数.

The expression itself, assuming you pass an actual lambda expression and not a method reference, is compiled as a separate, synthetic method. In addition to any formal arguments to the expected functional interface (e.g., a single String in the case of Consumer<String>), it will include arguments for any captured values.

在出现 lambda 表达式或方法引用的代码位置,会发出 invokedynamic 指令.第一次命中该指令时,会调用 LambdaMetafactory 上的引导程序方法.这个引导方法将修复委托给目标方法的目标功能接口的实际实现,这就是返回的内容.目标方法要么是表示 lambda 主体的合成方法,要么是使用 :: 运算符提供的任何命名方法.当一个实现功能接口的类被创建时,这个过程被推迟了;它不会在编译时发生.

At the code location where a lambda expression or method reference appears, an invokedynamic instruction is emitted. The first time this instruction is hit, a call is made into a bootstrap method on LambdaMetafactory. This bootstrap method will fix up an actual implementation of the target functional interface which delegates to the target method, and this is what gets returned. The target method is either the synthetic method representing the lambda body or whichever named method was provided using the :: operator. While a class that implements the functional interface is being created, the process is deferred; it does not happen at compile time.

最后,运行时使用引导结果1修补invokedynamic站点,这实际上是对生成的委托的构造函数调用,其中包含传入的任何捕获值,包括(可能)一个调用目标2.这通过删除后续调用的引导过程来减轻性能损失.

Finally, the runtime patches the invokedynamic site with the bootstrap result1, which is effectively a constructor call to the generated delegate with any captured values passed in, including (possibly) an invocation target2. This alleviates the performance hit by removing the bootstrapping process for subsequent calls.

1 参见 java.lang.invoke 链接时间"一章结尾,@Holger 提供.

1 See java.lang.invoke end of chapter "timing of linkage", courtesy of @Holger.

2 在没有捕获的 lambda 的情况下,invokedynamic 指令通常会解析为一个共享委托实例,可以在后续调用中重用,尽管这是一个实现细节.

2 In the case of a lambda which no captures, the invokedynamic instruction will usually resolve to a shared delegate instance that can be reused during subsequent calls, though this is an implementation detail.

这篇关于Java 8 lambdas 是否被编译为内部类、方法或其他东西?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆