Java 8 constructor method references
Asked Answered
K

1

9

I am reading Java 8 book, and it comes with a sample I reproduce:

@FunctionalInterface
public interface Action {
    public void perform();
}

An Implementor:

public final class ActionImpl implements Action {
    public ActionImpl() {
        System.out.println("constructor[ActionIMPL]");
    }

    @Override
    public void perform() {
        System.out.println("perform method is called..");
    }    
}

A caller:

public final class MethodReferences {

    private final Action action;

    public MethodReferences(Action action) {
        this.action = action;
    }

    public void execute() {
        System.out.println("execute->called");
        action.perform();
        System.out.println("execute->exist");
    }

    public static void main(String[] args) {
        MethodReferences clazz = new MethodReferences(new ActionImpl());
        clazz.execute();
    }
}

If this is called the following is print into the output:

constructor[ActionIMPL]
execute->called
perform method is called..
execute->exist

Everything is all right but if I use method references not perform message method is printed! Why is this, am I missing something?

If I use this code:

MethodReferences clazz = new MethodReferences(() -> new ActionImpl());
clazz.execute();

Or this code:

final MethodReferences clazz = new MethodReferences(ActionImpl::new);

This is printed:

execute->called
constructor[ActionIMPL]
execute->exist

No exception message or anything else is printed. I am using Java 8 1.8.25 64bit.

Update

For readers that are studying like me, this is the right running code.

I have created a class the caller.

Because I need to implement a empty method "perform from the Action functional interface" which I need to pass as parameter to class constructor MethodReference I reference the "constructor of the MethodReferenceCall which is a empty constructor" and I can use it.

public class MethodReferenceCall {
    public MethodReferenceCall() {
        System.out.println("MethodReferenceCall class constructor called");
    }

    public static void main(String[] args) {
        MethodReferenceCall clazz = new MethodReferenceCall();
        MethodReferences constructorCaller = new MethodReferences(MethodReferenceCall::new);
        constructorCaller.execute();
    }
}
Koehler answered 21/10, 2014 at 23:13 Comment(1)
You have an non-executed action inside another action. You could achieve what you want with the lambda MethodReferences clazz = new MethodReferences(() -> new ActionImpl().perform()); clazz.execute();Niall
D
14

This

MethodReferences clazz = new MethodReferences(() -> new ActionImpl());

does not use method reference, it uses a lambda expression. The functional interface is Action's

public void perform();

So

() -> new ActionImpl()

gets translated into something similar to

new Action() {
    public void perform() {
        new ActionImpl();
    }
}

Similarly, in

MethodReferences clazz = new MethodReferences(ActionImpl::new);

the ActionImpl::new, which does use a constructor reference, is translated into something like

new Action() {
    public void perform() {
        new ActionImpl();
    }
}

This ActionImpl::new does not invoke new ActionImpl(). It resolves to an instance of the expected type whose functional interface method is implemented as invoking that constructor.

Dorey answered 21/10, 2014 at 23:19 Comment(4)
could you explained a little more simple.. sorryKoehler
@Koehler A method reference is not a method invocation. Instead, it becomes the body of the target functional interface.Dorey
@Koehler Basically, your first (working) example creates a new ActionImpl, and when the perform method of that is called, it prints a message. The second example doesn't create a new ActionImpl. It creates a new object whose type is an anonymous class that implements Action. When the perform method of that anonymous-class object is called, its perform method creates a new ActionImpl (and then throws it away).Ambsace
Perfect explanation! What if ActionImpl implements 2 functional interfaces, How does it gets translated?Weiweibel

© 2022 - 2024 — McMap. All rights reserved.