首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有非静态上下文的Invokedynamic

具有非静态上下文的Invokedynamic
EN

Stack Overflow用户
提问于 2020-08-28 05:01:59
回答 1查看 81关注 0票数 1

我了解到字节码的invokedynamic指令调用lambda的static方法表示。

如果不正确,请告诉我。

如果正确,那么下面的代码是如何工作的?

代码语言:javascript
复制
String[] arr = new String[1];
Stream.of(arr).forEach((s) -> System.out.println(this));
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-28 07:34:53

说lambda表达式总是编译成static方法是不正确的。没有指定它们是如何编译的,这为捕获this的lambda表达式留出了两种不同的策略,比如您的s -> System.out.println(this)

  1. 使用实例方法:

私有空编译器$String$name(String s) { System.out.println(this);}

  1. 使用static方法:

私有静态空编译器$ static $name(TypeOfThis var0,String s) { System.out.println(var0);}

invokedynamic指令指向LambdaMetafactory中的引导方法时,这两种方法都同样工作得很好。在这两种情况下,invokedynamic指令都会有一个签名,使用一个TypeOfThis实例并生成一个Consumer<String>。从LambdaMetafactory的文档中,您可以得出这样的结论:它将把非static目标方法的接收方视为隐含的第一个参数,这使得这两个变体的功能签名完全相同。重要的是,使用者的accept方法的参数必须与列表的最后一个参数相对应。

我在实践中遇到过这两种策略,因此这确实是依赖于编译器的。

请注意,当使用方法引用时,这些策略也适用于源代码级别:

代码语言:javascript
复制
public class Example {
    BiConsumer<Example,String> variant1 = Example::instanceMethod;
    BiConsumer<Example,String> variant2 = Example::staticMethod;

    private void instanceMethod(String s) {
        System.out.println(this);
    }

    private static void staticMethod(Example instance, String s) {
        System.out.println(instance);
    }
}

这证明了方法接收器与static方法的第一个参数的等价性。但是,在绑定参数时,只有Consumer<String> c = this::instanceMethod;可以使用方法引用。LambdaMetafactory的其他绑定特性仅供编译器为lambda表达式生成的代码使用。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63627720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档