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.