代码之家  ›  专栏  ›  技术社区  ›  Nikolas Charalambidis

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

  •  6
  • Nikolas Charalambidis  · 技术社区  · 7 年前

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

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

    Method references 定义了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();
        }
    })....
    

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

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

    ... 然而,这只是 () -> new AtomicInteger(1).getAndIncrement()

    3 回复  |  直到 7 年前
        1
  •  5
  •   Eugene    7 年前

    new AtomicInteger(1) 返回一个实例,因此它是第二个实例。关于如何转换的确切细节是特定于实现的,但它是创建的单个实例,由 JLS 15.13.3

    首先,如果方法引用表达式以ExpressionName或Primary开头,则对该子表达式求值

    :: 评估 当第一次遇到它的声明时 .

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

        2
  •  2
  •   fdreger    7 年前

        3
  •  2
  •   Eran    7 年前

    你可以替换

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

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

    i、 e.本方法参考属于第二类方法参考- 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();
        }
    })...