1

According to this article, the method reference is defined as a method or constructor that is referenced without being executed, can anyone explain how is that possible?

For example:

public void main String(args[]) {
     List<Integer> numbers = Arrays.asList(1, 2, 3);
     // Below is a method reference that is referenced and being executed on run (prints the numbers!!)
     numbers.forEach(System.out::println);
}

If anyone can explain what statement 'referenced without being executed' means, it would be much appreciated :)

E_X
  • 3,722
  • 1
  • 14
  • 15

2 Answers2

2

When you call numbers.forEach(System.out::println), you reference the System.out::println method, but not execute it. For example, if numbers list is empty, then this method will never be executed. On the other hand, having this method reference, the forEach method can internally call this reference as many times as it want (in this case: for every list element).

Probably it would be easier to understand when you rewrite this code with equivalent anonymous class:

 numbers.forEach(new Consumer<Integer>() {
     public void accept(Integer num) {
         System.out.println(num);
     }
 });

Here you can see that method reference is actually creation of helper object of Consumer type, without actually calling the referenced method.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
2

Your statement numbers.forEach(System.out::println); is an inlined version of

Consumer<Integer> c=System.out::println;
numbers.forEach(c);

This should better illustrate that the first line creates a reference to the method println of the instance of a PrintWriter found in System.out and doesn’t executed it. It doesn’t print anything—it wouldn’t even know what to print. The object to be printed is a parameter of the created Consumer’s accept method.

The second line numbers.forEach(c) will eventually print every number, because the specified Consumer has been created as a reference System.out::println. The forEach method receives an arbitrary Consumer and will perform it’s encapsulated action for every element by invoking said accept method for each element, passing the element as an argument.

Of course, you can inline the variable c getting your original statement numbers.forEach(System.out::println);, but then, difference between the consumer creation and execution is not so obvious, but also not that relevant for this use case. In general, you could keep the Consumer much longer than for a single use case.

Holger
  • 285,553
  • 42
  • 434
  • 765