Java 8 lambdas是编译为内部类,方法还是别的什么? [英] Are Java 8 lambdas compiled as inner classes, methods or something else?

查看:149
本文介绍了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

文章建议,lambdas 不是实现为anon内部类(由于性能)。
它给出了一个示例,可以将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 Factory实例..

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

那么lambdas是如何实现的?

How are lambdas implemented then?

推荐答案

表达式本身(假设您传递实际的lambda表达式而不是方法引用)被编译为单独的合成方法。除了预期功能接口的任何形式参数之外(例如,在 Consumer< String> 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 上调用bootstrap方法。这个引导方法将修复目标功能接口的实际实现,该接口委托给目标方法,这就是返回的内容。目标方法是表示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.

最后,运行时使用引导结果 invokedynamic 站点> 1 ,它实际上是对生成的委托的构造函数调用,其中传入了任何捕获的值,包括(可能)调用目标 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 参见< a href =http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/package-summary.html#indyinsn =noreferrer> 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天全站免登陆