1

I have been learning java for past few months and just started to get into lambda functions. I recently switched my IDE and noticed a warning saying "Can be replaced with method reference" on codes like this.

   List<Integer> intList = new ArrayList<>();
        intList.add(1);
        intList.add(2);
        intList.add(3);

        intList.forEach(num -> doSomething(num));

    voiddoSomething(int num) {
        System.out.println("Number is: " + num);
    }

After some digging, I realized that instead of the line

 intList.forEach(num -> doSomething(num));

I can just use

 intList.forEach(this::doSomething);

This is just amazing. A few days ago I did not even knew about lambdas and was using for loops to do operations like this. Now I replaced my for loops with lambdas and even better, I can replace my lambdas with method references. The problem is that I don't really understand how all this works internally. Can anyone please explain or provide a good resource explaining how the doSomething function is called and the argument is passed to it when we use method reference?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Saik
  • 993
  • 1
  • 16
  • 40
  • Possible duplicate of [lambda with non-static methods in Java 8](https://stackoverflow.com/questions/25784337/lambda-with-non-static-methods-in-java-8) – Joe Dec 23 '17 at 10:41
  • Read the tutorial: [https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html) – fps Dec 23 '17 at 14:00

3 Answers3

1

The double-colon operator is simply a convenience operator for doing the same thing that your lambda is doing. Check out this page for more details: https://javapapers.com/core-java/java-method-reference/

Josh Withee
  • 9,922
  • 3
  • 44
  • 62
1

The double colon is simply syntactic sugar for defining a lambda expression whose parameters and return type are the same as an existing function. It was created to to allow lambdas to more easily be added with existing codebases.

Calling the forEach method of a List<Integer> object takes as its parameter any object implementing the Consumer functional interface. Your lambda num -> doSomething(num) itself happens to fulfill the formal requirements of this interface.

Thus, you can use the double colon as syntactic sugar for that lambda expression.

In general, if you have an object obj with method func, which accepts parameters params... then writing obj::func is equivalent to the lambda (params...) -> obj.func(params...).

In your case, o is this (the current object), which has a method doSomething(), which takes an integer parameter, thus, this::doSomething is equivalent to num -> doSomething(num).

ubadub
  • 3,571
  • 21
  • 32
1

Given you've mentioned that it's only until recently you started getting into functional programming I'd like to keep things as simple and straightforward as possible, but note that with just the little code you've provided, we could derive a lot both from the high-level view of things as well the low-level view.

Can anyone please explain or provide a good resource explaining how the doSomething function is called and the argument is passed to it when we use method reference?

how the doSomething function is called is left to the library (internal iteration) regardless of whether we use a method reference or a lambda expression, so essentially we specify the what not the how meaning we provide to the forEach method a behaviour (a function) that we want to execute for each element of the source intList and not necessarily how it should go about its work.

This is then left to the library to apply (execute) the specified function of doSomething for each element of the source intList.

Method references can be seen as a shorthand for lambdas calling only a specific method. The benefit here is that by referring to a specific method name explicitly, your code gains better readability, therefore, making it easier to read and follow and in most cases reading code with method references reads as the problem statement which is a good thing.

It's also important to know that not any given function can be passed to the forEach terminal operation as every method that accepts a behaviour has a restriction on the type of function allowed. This is accomplished with the use of functional interfaces in the java.util.function package.

Lastly but not least, in terms of refactoring it's not always possible to use method references nor is it always better to use lambdas expressions over code that we used prior to Java-8. However, as you go on with your journey of learning the Java-8 features, a few tips to better your code are to try:

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126