Anton
Anton

Reputation: 57

Custom functional interface as method argument

I have the code below that does produce expected result. Could somebody explain what's happening behind the curtains? I don't understand how does the compiler/JVM knows that it's needed to invoke store(String str) on the Storer object or how does it define the doSomething(Storer s, String str) implementation.

Storer.java

public class Storer {
    private List<String> storer = new ArrayList<>();

    public void store(String str) {
        storer.add(str);
    }

    @Override
    public String toString() {
        return "Storer [storer=" + storer + "]";
    }

}

MyInterface.java

@FunctionalInterface
public interface MyInterface {
    public abstract void doSomething(Storer s, String str);
}

Executor.java

public class Executor {
    public void doStore(Storer storer, String s, MyInterface p) {
        p.doSomething(storer, s);
    }
}

TestFunctionalInterfaces.java

public class TestFunctionalInterfaces {
    public static void main(String[] args) {
        Storer storer = new Storer();

        Executor test = new Executor();
        test.doStore(storer, "I've got added", Storer::store);

        System.out.println(storer);
    }
}

An output is:

Storer [storer=[I've got added]]

Thanks in advance.

Upvotes: 3

Views: 564

Answers (2)

Mathias
Mathias

Reputation: 91

The method reference Store::storer is equivalent to the lambda (s, str) -> s.store(str). In general, given a functional interface that expects args a1, a2, a3, ..., a method reference of this type is equivalent to a lambda that calls a1.namedMethod(a2, a3, ...). See this answer.

Upvotes: 1

tomgeraghty3
tomgeraghty3

Reputation: 1254

Storer::store is a method reference which can be used in place of any @FunctionalInterfaces. What you've got here is essentially a shorthand of an implementation of My Interface. The equivalent being :

public class MyInterfaceImpl implements MyInterface {
    public void doSomething(Storer storer, String str) {
       storer.store(str);
    } 
}

This implementation (specified through your method reference) is why storer.store() is executed... because of the implementation of MyInterface you've specified, and passed to, your Executor. The compiler is smart enough to match the implemention/method reference to the arguments you supplied

Upvotes: 3

Related Questions