Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have encountered a short time ago with a competitive answer better than mine that uses a quite new method reference to me as replacement of lambda.

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

I looked the Oracle specifications about the Method references and there are defined 4 types:

  • Reference to a static method ContainingClass::staticMethodName
  • Reference to an instance method of a particular object containingObject::instanceMethodName
  • Reference to an instance method of an arbitrary object of a particular type ContainingType::methodName
  • Reference to a constructor ClassName::new

I struggle with categorizing this one. I haven't found any question on SO or anything relevant explained in the docs. How would be this translated to an anonymous class?

My suspicion is:

IntStream.generate(new IntSupplier() {

    AtomicInteger atom = new AtomicInteger(1);

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

... I don't understand how is this possible. At first sight, I would guess the expression is:

IntStream.generate(new IntSupplier() {

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

... yet this is nothing else than () -> new AtomicInteger(1).getAndIncrement().

Where is this kind of expression defined and how it exactly would be rewritten in the lambda/anonymous class?

like image 689
Nikolas Charalambidis Avatar asked Dec 03 '18 09:12

Nikolas Charalambidis


2 Answers

Well new AtomicInteger(1) returns an instance, so it's the second one. The exact details of how this is translated are implementation specific, but it's a single instance created and this is back-ed up by the JLS 15.13.3

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

In plain english, the part before :: is evaluated when it's declaration is first encountered.

Your assumption how this is translated is almost correct, it's like generating an instance outside of the function itself and using that - since it is effectively final, this is permitted.

like image 72
Eugene Avatar answered Sep 30 '22 19:09

Eugene


It's simply the second type: a reference to a method of a specific object, there's no additional logic behind the curtain.

like image 24
fdreger Avatar answered Sep 30 '22 18:09

fdreger