1

There is this other question that only explains passing function references but this does not answer the question below on how this Java assignment works, the conversion to this Supplier object and when this happens.

I have the following code snippet and struggling a bit to understand it and probably I am not the only one. Can someone give a "for dummies" explanation of this code (both the Supplier pattern and the assignment using double-colon (::) operator. When is Java actually making the function call? My expectation is that objectFactorySupplier becomes a function pointer.

private Supplier<ObjectFactory> getObjectFactorySupplier(String name) {
    // how does this assignment work?
    Supplier<ObjectFactory> objectFactorySupplier = this::getObjectFactory;
    ...
    return objectFactorySupplier;
}

private ObjectFactory getObjectFactory() {
    ObjectFactory factory = new ObjectFactorySupplier().get();
    ...
    return factory;
}
Gabriel Petrovay
  • 20,476
  • 22
  • 97
  • 168
  • 2
    Does this help, regarding double-colon: https://stackoverflow.com/questions/20001427/double-colon-operator-in-java-8 ? – Oozeerally May 01 '20 at 08:11
  • 1
    It is called method reference, but to better grasp it you probably should start with learning about [lambdas](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html), but to better understand lambdas you probably need to start from learning about streams added in Java 8 ([summary of its package](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html) is quite nice educational material). This is also nice resource http://www.lambdafaq.org/ – Pshemo May 01 '20 at 08:28
  • 1
    Note that lambdas dont have anything to do with streams, the stream API is just one of the biggest possibilities to use lambdas. In order to understand lambdas one must learn (functional) interfaces. In Java, a lambda is nothing more than a fancy way to create an instance of an interface, like a regular class or anonymous class. Same for method references. – Zabuzard May 01 '20 at 08:33
  • @AdilOoze certainly that other question helps understanding the double-colon but the answer that I was actually looking for (posted already below) is actually about the functional interfaces. Missing this notion confused me. In the question you mentioned this is also in the 2nd most voted answer: https://stackoverflow.com/a/22245383/454103 – Gabriel Petrovay May 01 '20 at 08:36

3 Answers3

2
  • Supplier is a functional interface introduced as part of Java 8. So, a functional interface can be substituted within lambda expression, for example: Runnable, Callable etc. So, by definition, it represents a supplier of results.
  • :: is a method reference

In your code,

Supplier<ObjectFactory> objectFactorySupplier = this::getObjectFactory;

this::getObjectFactory returns a method reference to your private method. And this method reference is assigned to the left hand side of the expression. And by its code definition, it basically supplies a objectFactory. It can be assigned because it qualifies for the definition of Supplier functional interface

Now, this method reference is used to get objectFactory ultimately.

Gabriel Petrovay
  • 20,476
  • 22
  • 97
  • 168
a3.14_Infinity
  • 5,653
  • 7
  • 42
  • 66
1

The statement

Supplier<ObjectFactory> objectFactorySupplier = this::getObjectFactory;

could also b represented with lambda as

Supplier<ObjectFactory> objectFactorySupplier = () -> getObjectFactory();

which is easy to read, that without any input supply the return type of getObjectFactory method call.

And what does it return? an ObjectFactory! So it's easy to be inferred as and assigned to a Supplier<ObjectFactory> variable.

Naman
  • 27,789
  • 26
  • 218
  • 353
0

What is Supplier interface?

It is a functional interface. You can declare a lambda in java and use a functional interface as its target. Also it provides a single abstract method get() which is also called a functional method. get() is used to fetch the results that are returned by the Supplier whenever it is invoked.

Hence you can declare a supplier, invoke it and fetch its results by using the get.

An example

A very simple example to understand how to create a supplier and then use it. Here I have created a supplier for my Rectangle which will return a new rectangle of a width and height whenever the supplier is invoked.

public class Main
{
    // A simple class
    public static class Rectangle
    {
        int width, height;
        public Rectangle(int w, int h) {
            width = w; height = h;
        }       
        @Override
        public String toString() {
            return String.format("width=%s height=%s", width, height);
        }
    }

    public static void main(String[] args) {
        // How to create a supplier?
        Supplier<Rectangle> rectSupp = new Supplier<Rectangle>() {
            /**
             * Important to implement this functional method
             */
            @Override
            public Rectangle get() {
                return new Rectangle(1, 2);
            }
        };

        // How to create a lambda supplier?
        Supplier<Rectangle> lambdaRectSupp = () -> new Rectangle(3, 4);

        System.err.println(rectSupp.get());
        System.err.println(lambdaRectSupp.get());
    }
}
Pbd
  • 1,219
  • 1
  • 15
  • 32