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

Nik*_*las 6 java lambda java-8 functional-interface

我很久以前就遇到过一个比我更好的竞争性答案,它使用了一个非常新的方法参考我作为lambda的替代品.

Stream.generate(new AtomicInteger(1)::getAndIncrement)...
Run Code Online (Sandbox Code Playgroud)

我查看了有关Method引用的Oracle规范,并定义了4种类型:

  • 参考静态方法 ContainingClass::staticMethodName
  • 引用特定对象的实例方法 containingObject::instanceMethodName
  • 引用特定类型的任意对象的实例方法 ContainingType::methodName
  • 引用构造函数 ClassName::new

我很难对这个进行分类.我没有在SO上发现任何问题或在文档中解释任何相关的问题.怎么会被翻译成匿名课程?

我的怀疑是:

IntStream.generate(new IntSupplier() {

    AtomicInteger atom = new AtomicInteger(1);

    @Override
    public int getAsInt() {
        return atom.getAndIncrement();
    }
})....
Run Code Online (Sandbox Code Playgroud)

......我不明白这是怎么回事.乍一看,我猜是表达式是:

IntStream.generate(new IntSupplier() {

    @Override
    public int getAsInt() {
        return new AtomicInteger(1).getAndIncrement();
    }
})....
Run Code Online (Sandbox Code Playgroud)

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

这种表达式在哪里定义,以及如何在lambda/anonymous类中重写?

Eug*_*ene 5

好了new AtomicInteger(1)返回一个实例,所以它是第二个.有关如何翻译的确切细节是特定于实现的,但它是一个单独的实例,并由JLS 15.13.3进行备份.

首先,如果方法引用表达式以ExpressionName或Primary开头,则计算此子表达式

用简单的英语,在首次遇到声明时::评估之前的部分.

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

  • "当它首次遇到声明时"会产生误导,因为每次*都会对它进行评估*,遇到表达式`expression :: name`.但必须强调的是,对生成的函数实例的评估不会遇到它.这与lambda表达式不同,lambda表达式将在每次计算函数时计算` - >`右侧的表达式. (3认同)