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>.