[英]Invokedynamic with non-static context
I learnt that invokedynamic
instruction of bytecode calls a static
method representation of lambda.我了解到,
invokedynamic
字节码指令调用static
拉姆达的方法表示。
Please let me know if that is incorrect.如果这不正确,请告诉我。
if correct, then how is below code working?如果正确,那么下面的代码如何工作?
String[] arr = new String[1];
Stream.of(arr).forEach((s) -> System.out.println(this));
It's not correct to say that lambda expressions were always compiled to a static
method.说 lambda 表达式总是被编译为
static
方法是不正确的。 It's not specified, how they are compiled, which leaves room for two different strategies for a lambda expression that captures this
, like your s -> System.out.println(this)
.没有指定它们是如何编译的,这为捕获
this
的 lambda 表达式的两种不同策略留下了空间,例如您的s -> System.out.println(this)
。
use an instance method:使用实例方法:
private void compiler$chosen$name(String s) { System.out.println(this); }
use a static
method:使用
static
方法:
private static void compiler$chosen$name(TypeOfThis var0, String s) { System.out.println(var0); }
Both methods work equally well when the invokedynamic
instruction points to a bootstrap method in the LambdaMetafactory
.当
invokedynamic
指令指向LambdaMetafactory
的引导方法时,这两种方法同样有效。 In either case, the invokedynamic
instruction will have a signature consuming a TypeOfThis
instance and producing a Consumer<String>
.在任何一种情况下,
invokedynamic
指令都会有一个签名,使用TypeOfThis
实例并生成一个Consumer<String>
。 From the documentation of the LambdaMetafactory
, you can derive that it will treat the receiver of a non- static
target method like an implied the first argument, which makes the functional signature of both variants identical.从
LambdaMetafactory
的文档中,您可以得出它会将非static
目标方法的接收者视为隐含的第一个参数,这使得两个变体的功能签名相同。 All that matters, is that the argument to the consumer's accept
method has to correspond to the last argument of the list.重要的是消费者的
accept
方法的参数必须对应于列表的最后一个参数。
I've encountered both strategies in practice, so this is indeed compiler dependent.我在实践中遇到过这两种策略,所以这确实依赖于编译器。
Note that these strategies also work on source code level, when using method references:请注意,当使用方法引用时,这些策略也适用于源代码级别:
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);
}
}
This demonstrates the equivalence of a method receiver and the the first argument to a static
method.这演示了方法接收器和
static
方法的第一个参数的等效性。 However, when it comes to binding an argument, only Consumer<String> c = this::instanceMethod;
但是,当涉及到绑定参数时,只有
Consumer<String> c = this::instanceMethod;
works with method references.使用方法引用。 The other binding features of the
LambdaMetafactory
are only used by compiler generated code for lambda expressions. LambdaMetafactory
的其他绑定功能仅由编译器生成的 lambda 表达式代码使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.