关于Java lambda等式和/或实例化

Ily*_*kov 13 java lambda java-8

为什么下面的片段在第二次传递时打印为真?它应该不是一个新的实例吗?

import java.util.function.Supplier;

public class Foo {
    public static void main(String[] args) throws Exception {
        Supplier<Long> old = () -> System.nanoTime();

        for (int i = 0; i < 3; i++) {
            /* false true true
            Supplier<Long> foo = System::nanoTime;*/

            Supplier<Long> foo = () -> System.nanoTime();

            /* false false false
            Supplier<Long> foo = new Supplier<Long>() {
                @Override
                public Long get() {
                    return System.nanoTime();
                }
            };
            //*/

            System.out.printf("%s %s %s%n", foo == old, foo, old);

            old = foo;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

false Foo$$Lambda$2/122883338@1ddc4ec2 Foo$$Lambda$1/1534030866@133314b
true Foo$$Lambda$2/122883338@1ddc4ec2 Foo$$Lambda$2/122883338@1ddc4ec2
true Foo$$Lambda$2/122883338@1ddc4ec2 Foo$$Lambda$2/122883338@1ddc4ec2
Run Code Online (Sandbox Code Playgroud)

sh0*_*0ru 11

查看有关如何实现lambda的文章.

本质上,编译器将您的两个System.nanoTime()变为您的类中的以下静态方法:

static Long lambda$1() {
    return System.nanoTime();
}

static Long lambda$2() {
    return System.nanoTime();
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个对每个目标类型的常量引用来Supplier<Long>使用LambdaMetaFactory.坦率地说,我很遗憾Java编译器没有意识到lambda主体是相同的,只创建了一个实例.如果Java编译器足够智能,那么每一行都应该打印出来true!

  • 即使编译器足够聪明地将`lambda $ 1()`和`lambda $ 2()`折叠到一个方法中,引用该方法的不同lambda创建站点仍然会导致创建不同的对象实例(甚至是不同的类).这可以通过多次使用类似`System :: nanoTime`的方法引用来证明,因为这些*do*指向相同的目标方法,因为没有生成合成方法.尽管如此,考虑到Oracle目前的实施*,它们还会产生不同的对象*. (2认同)