为什么Java-8 lambda需要invokeDynamic byteCode来调用接口方法

时间:2016-01-23 13:50:23

标签: java lambda java-8

您好我正在尝试理解使用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)都在编译期间定义了吗?

1 个答案:

答案 0 :(得分:10)

保存lambda表达式主体的方法是通过invokedynamic调用而不是。与任何其他接口方法一样,函数接口的实现通过invokeinterface调用。调用者甚至不知道是否为lambda表达式生成了实现接口的对象。

这个生成的接口实现如何调用合成方法,是特定于JRE的,但通常是通过普通调用(invokestaticinvokevirtualinvokespecial)来实现的。只有访问权限遵循不同的规则,即尽管是private,生成的类可以调用该方法。

invokedynamic指令用于接口实现的实例化,因此它允许任意的,未知的实现类,包括在编译时不存在的类,但是在运行时生成。它还可以返回现有实例而不是创建新实例,这对于普通实例创建代码是不可能的。