The Comparator
interface required for Arrays.sort(T[],Comparator<T>)
has a method that accepts two object references of the same type T
, and returns an integer.
There is a bit of "magic" in method references. What Java does is wrap the method in such a way that it will fit the interface requirement.
The interface, of course, doesn't require a static method. But the wrapping can create a method that calls a static method, as in the Tutorial's first example:
public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
}
It wraps it in such a way that you get something similar to
new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return Person.compareByAge(a,b);
}
}
Which satisfies the interface.
But in the example in the section "Reference to an Instance Method of an Arbitrary Object of a Particular Type", it wraps it differently. It needs a method that receives two strings, but it has a method that only receives one. This is how String::compareToIgnoreCase
is defined:
public int compareToIgnoreCase(String str)
But in this case, it's an instance method. What Java does now is, because this method belongs to an object of type String
, and accepts an object of type String
it is easy to build a "wrap" around it that makes it into a method that accepts two objects, much like the lambda expression:
(String a, String b) -> {
return a.compareToIgnoreCase( b );
}
Or, if we imagine a formal wrapping as a Comparator
:
new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareToIgnoreCase(b);
}
}
So, the fact that it's an instance method that belongs to type T
, accepts type T
and returns int
allows Java to wrap it appropriately so it fits the Comparator
interface.
But int compare(Demo2 o1, Demo2 o2)
doesn't fit that pattern. It accepts two parameters. If a method accepts two parameters, it must be a static method to fit the wrapping rules - there is no way to pass the "this" object into the Comparator
interface. So it tries to wrap it as a static method, and fails, as it is not a static method.
Bottom line: you got the error, because for this particular type of method reference, you need an instance method with only one parameter of the same type as the class.
As @Holger mentions in a comment, if you have a new class you are building, you shouldn't put a comparison method in it specifically for this sort of sorting task. If the class has a natural ordering, make it Comparable
and use Arrays.sort(Object[])
. If it doesn't, and you need to sort it sometimes based on any of its attributes, use a lambda expression or Comparator.comparing(Demo2::getI)
which makes better use of an existing getter for the specific purpose of comparison.