Lambda表达式与方法参考实现的详细信息

hit*_*wen 4 java lambda

鉴于这种:

class MyClass {
    static class A {
        public boolean property() {
            return Math.random() < 0.5;
        }
    }

    static List<A> filterLambda(List<A> list) {
        return list.stream().filter(a -> a.property()).collect(Collectors.toList());
    }

    static List<A> filterMethodCall(List<A> list) {
        return list.stream().filter(A::property).collect(Collectors.toList());
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 编译器对每种方法执行的操作有什么区别?
  • 如果有的话,内存使用或运行时间是否有所不同?(即使很小,问题也只是学术上的)

PD:我知道这个问题与类似,但是我认为这个问题没有得到正确解决。

hit*_*wen 6

这是由Brett Oken链接的Brian Goetz的文档的摘录:

当编译器遇到lambda表达式时,它首先将lambda主体降低(降低)到方法中其参数列表和返回类型与lambda表达式的参数匹配,并可能带有一些其他参数(用于从词法范围捕获的值,如果有的话)。在将捕获lambda表达式的点上,它会生成一个invokedynamic调用站点,当调用该函数时,将返回lambda转换为的功能接口的实例。此调用站点称为给定lambda的lambda工厂。lambda工厂的动态参数是从词法范围中捕获的值。lambda工厂的bootstrap方法是Java语言运行时库中的一种标准化方法,称为lambda元工厂。静态引导程序参数捕获在编译时有关lambda的已知信息(它将转换为lambda的功能接口,

方法引用与lambda表达式的处理方式相同,不同之处在于,大多数方法引用不需要分解为新方法;我们可以简单地为引用的方法加载一个常量方法句柄,并将其传递给元工厂。

从同一文档中提取的示例:

例如,考虑一个捕获字段minSize的lambda:

list.filter(e -> e.getSize() < minSize )
Run Code Online (Sandbox Code Playgroud)

我们将其作为实例方法进行解糖,并将接收器作为第一个捕获的参数传递:

list.forEach(INDY((MH(metaFactory), MH(invokeVirtual Predicate.apply),
                    MH(invokeVirtual B.lambda$1))( this ))));

private boolean lambda$1(Element e) {
    return e.getSize() < minSize; }
Run Code Online (Sandbox Code Playgroud)

list.filter(String::isEmpty)
Run Code Online (Sandbox Code Playgroud)

被翻译为:

list.filter(indy(MH(metaFactory), MH(invokeVirtual Predicate.apply),
             MH(invokeVirtual String.isEmpty))()))
Run Code Online (Sandbox Code Playgroud)