Reputation: 1664
I am trying to work out how this works.
I am going to list what I believe is happening and hopefully someone can tell me I am wrong in places. Or tell me how/why this works.
public BiConsumer<List<T>, T> accumulator() {
return List::add;
}
accumulator
returns a reference to the add
method on the context of a List
as the BiConsumer
add
method on a List
is actually a Function<T, Boolean>
, takes in T
and returns a booleanThis is where I get into the guessing realm.
add
method, on the instance of the List
that is the first argument of the BiConsumer
. I know internally it must be doing.
public BiConsumer<List<T>, T> accumulator() {
return (list, item) -> list.add(i);
}
I understand that it can ignore the return type of the add
method, so it can pretend Function<A, B>
is Consumer<A>
But I just don't understand the black magic that turns a BiConsumer
runs a Consumer
or Function
on the instance of the first argument of the BiConsumer
.
Upvotes: 3
Views: 749
Reputation: 271685
It's not black magic. It is well specified here.
The following is an example of a reference to an instance method of an arbitrary object of a particular type:
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" }; Arrays.sort(stringArray, String::compareToIgnoreCase);
The equivalent lambda expression for the method reference
String::compareToIgnoreCase
would have the formal parameter list(String a, String b)
, where a and b are arbitrary names used to better describe this example. The method reference would invoke the methoda.compareToIgnoreCase(b)
.
When you have something like SomeType::instanceMethod
, it can be converted to a function accepting two arguments, the first being the instance to call the method on. It just can, because the language spec says so.
Upvotes: 2