【问题标题】:On Java lambda equality and/or instantiation [duplicate]关于 Java lambda 相等和/或实例化 [重复]
【发布时间】:2016-01-07 10:41:58
【问题描述】:

为什么下面的 sn-p 在第二次通过时打印为 true?不应该是一个新的实例吗?

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;
        }
    }
}

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

【问题讨论】:

  • 我想这是一个编译器优化。循环的每次迭代都不需要新实例,因此编译器不会打扰。
  • 你为什么编辑重新添加不相关的 cmets ? (只是想知道,也许它们是相关的)
  • @Jean-FrançoisSavard 我认为他们添加了一些上下文,:: 的行为类似于()-&gt;,但不像new
  • 谈话很便宜,代码代表自己。 cmets 不提供额外的 IMO 价值。

标签: java lambda java-8


【解决方案1】:

查看article,了解 lambda 是如何实现的。

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

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

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

然后使用LambdaMetaFactory 创建对每个目标类型为Supplier&lt;Long&gt; 的常量引用。坦率地说,我很失望 Java 编译器没有意识到 lambda 主体是相同的并且只创建一个实例。如果 Java 编译器足够聪明,每一行都应该打印 true!

【讨论】:

  • 即使编译器足够聪明,可以将 lambda$1()lambda$2() 合并为一个方法,引用该方法的不同 lambda 创建站点仍然会导致创建不同的对象实例(甚至不同的类) .这可以通过多次使用像System::nanoTime 这样的方法引用来轻松证明,因为这些确实指向相同的目标方法,因为没有生成合成方法。尽管如此,它们会产生不同的对象鉴于 Oracle 当前的实现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多