Java 中作为 lambda 表达式的完整构造函数调用的方法引用

Method reference with a full constructor call as a lambda expression in Java

不久前,我遇到了一个 比我的更好的方法,它使用了一个相当新的方法来替代 lambda。

Stream.generate(new AtomicInteger(1)::getAndIncrement)...

我查看了有关 Method references 的 Oracle 规范,其中定义了 4 种类型:

我很难对这个进行分类。我没有发现任何关于 SO 的问题或文档中解释的任何相关内容。这将如何翻译成匿名 class?

我的怀疑是:

IntStream.generate(new IntSupplier() {

    AtomicInteger atom = new AtomicInteger(1);

    @Override
    public int getAsInt() {
        return atom.getAndIncrement();
    }
})....

...我不明白这怎么可能。乍一看,我猜表达式是:

IntStream.generate(new IntSupplier() {

    @Override
    public int getAsInt() {
        return new AtomicInteger(1).getAndIncrement();
    }
})....

...但这就是() -> new AtomicInteger(1).getAndIncrement()

这种表达式是在哪里定义的,在lambda/anonymousclass中如何重写?

你可以替换

Stream.generate(new AtomicInteger(1)::getAndIncrement)...

AtomicInteger containingObject = new AtomicInteger(1);
Stream.generate(containingObject::getAndIncrement)...

即此方法引用属于第二类方法引用 - Reference to an instance method of a particular object.

您应该注意 AtomicInteger 实例创建不是 IntSupplier 实现的一部分。 Java 7 等价物是:

AtomicInteger aint = new AtomicInteger(1);
IntStream.generate(new IntSupplier() {

    @Override
    public int getAsInt() {
        return aint.getAndIncrement();
    }
})...

.

就是第二种:对特定对象的方法的引用,幕后没有额外的逻辑。

new AtomicInteger(1)returns一个实例,所以这是第二个。如何翻译的确切细节是特定于实现的,但它是创建的单个实例,并且由 JLS 15.13.3

支持

First, if the method reference expression begins with an ExpressionName or a Primary, this subexpression is evaluated

用简单的英语来说,:: 之前的部分在 第一次遇到它的声明时被评估

你的假设几乎是正确的,这就像在函数本身之外生成一个实例并使用它 - 因为它实际上是最终的,所以这是允许的。