您好我正在尝试理解使用Lambda表达式的优点,我听说JVM使用invokeDynamic byteCode来执行lambda表达式会提高性能相比XXXX(对不起我不知道,它可能是一个匿名者内在的)。
我的问题是为什么Lambda表达式需要invokeDynamic byteCode。
例如:
public class LambdaTest {
public static void main(String[] args) {
MathOperation addition = (int a, int b) -> a + b;
addition.operation(1, 2);
}
private static int operate(int a, int b, MathOperation operation){
return operation.operation(a, b);
}
interface MathOperation {
int operation(int a, int b);
}
}
其中lambda表达式(int a, int b) -> a + b;
可以简单地用于静态方法,如
private static int lambda$1(int a, int b) {
return a + b;
}
最终可以使用invokstatic
byteCode调用吗?
更多问题:当编译时本身定义所有参数类型返回类型时,lambda表达式试图实现的动态性是什么。
例如:在lambda
表达式(int a, int b) -> a + b;
中,所有(argument type, return type
)都在编译期间定义了吗?
答案 0 :(得分:10)
保存lambda表达式主体的方法是通过invokedynamic
调用而不是。与任何其他接口方法一样,函数接口的实现通过invokeinterface
调用。调用者甚至不知道是否为lambda表达式生成了实现接口的对象。
这个生成的接口实现如何调用合成方法,是特定于JRE的,但通常是通过普通调用(invokestatic
,invokevirtual
或invokespecial
)来实现的。只有访问权限遵循不同的规则,即尽管是private
,生成的类可以调用该方法。
invokedynamic
指令用于接口实现的实例化,因此它允许任意的,未知的实现类,包括在编译时不存在的类,但是在运行时生成。它还可以返回现有实例而不是创建新实例,这对于普通实例创建代码是不可能的。