我了解到字节码的invokedynamic指令调用lambda的static方法表示。
如果不正确,请告诉我。
如果正确,那么下面的代码是如何工作的?
String[] arr = new String[1];
Stream.of(arr).forEach((s) -> System.out.println(this));发布于 2020-08-28 07:34:53
说lambda表达式总是编译成static方法是不正确的。没有指定它们是如何编译的,这为捕获this的lambda表达式留出了两种不同的策略,比如您的s -> System.out.println(this)。
私有空编译器$String$name(String s) { System.out.println(this);}
static方法:私有静态空编译器$ static $name(TypeOfThis var0,String s) { System.out.println(var0);}
当invokedynamic指令指向LambdaMetafactory中的引导方法时,这两种方法都同样工作得很好。在这两种情况下,invokedynamic指令都会有一个签名,使用一个TypeOfThis实例并生成一个Consumer<String>。从LambdaMetafactory的文档中,您可以得出这样的结论:它将把非static目标方法的接收方视为隐含的第一个参数,这使得这两个变体的功能签名完全相同。重要的是,使用者的accept方法的参数必须与列表的最后一个参数相对应。
我在实践中遇到过这两种策略,因此这确实是依赖于编译器的。
请注意,当使用方法引用时,这些策略也适用于源代码级别:
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表达式生成的代码使用。
https://stackoverflow.com/questions/63627720
复制相似问题