Java 8 and method references - specifically compareToIgnoreCase
This is the difference between a method reference on some object and a method reference on the object being processed.
First the Oracle examples
Lets look at this first case:
public int compareByName(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
Here, the method compareByName
is called on the passed in instance of myComparisonProvider
with each pair of arguments in the sort
algorithm.
So here, when comparing a
and b
we actually call:
final int c = myComparisonProvider.compareByName(a,b);
Now, in the second case:
String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
You are sorting a String[]
so the method compareToIgnoreCase
is called on the String
instance currently being sorted with the other String
as an argument.
So here, when comparing a
and b
we actually call:
final int c = a.compareToIgnoreCase(b);
So these are two different cases:
- one where you pass in a method on an arbitrary object instance; and
- one where you pass in a method to be called on the instance being processed.
Onto your examples
Now in your first example, you also have a String[]
and you try and sort it. So:
Arrays.sort(stringArray, FakeString::compare);
So here, when comparing a
and b
we actually call:
final int c = FakeString.compare(a, b);
The only difference is compare
is static
.
Arrays.sort(stringArray, FakeString::compareToIgnoreCase);
Now, the String[]
is not a FakeString[]
so we cannot call this method on String
. Therefore we must be calling a static
method on FakeString
. But we cannot do this either, because we require a method (String, String) -> int
but we only have (String) -> int
- compilation error.
In the second example the problem is exactly the same, as you still have a String[]
. And compareToIgnoreCase
has the wrong signature.
TL;DR:
The point you are missing is that in the String::compareToIgnoreCase
example; the method is called on the String
currently being processed.
In FakeString
, Your compareToIgnoreCase
has a single String
argument, so it can't come in place of a Comparator<String>
, which requires a method with two String arguments.
In FakeString2
, your compareToIgnoreCase
has an implicit FakeString
argument (this) and a String argument, so, again, it can't come in place of a Comparator<String>
.