The Comparator interface needed for Arrays.sort(T[],Comparator<T>) has a method that takes two references to objects of the same type T and returns an integer.
There is a bit of magic in the method links. What Java does is to wrap the method in such a way that it meets the interface requirement.
The interface, of course, does not require a static method. But the shell can create a method that calls the static method, as in the first Tutorial example:
public static int compareByAge(Person a, Person b) { return a.birthday.compareTo(b.birthday); }
He wraps it in such a way that you get something like
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 "Link to an instance method of an arbitrary object of a certain type", it wraps it in different ways. He needs a method that gets two strings, but has a method that gets only one. Here's how String::compareToIgnoreCase defined:
public int compareToIgnoreCase(String str)
But in this case, it is an instance method. What Java is doing now, because this method refers to an object of type String and accepts an object of type String , it is easy to build a wrapper around it, which turns it into a method that accepts two objects, very similar to the lambda expression:
(String a, String b) -> { return a.compareToIgnoreCase( b ); }
Or, if you imagine formal packaging as a Comparator :
new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareToIgnoreCase(b); } }
So, the fact that this is an instance method that belongs to type T , takes type T and returns int , allows Java to wrap it appropriately so that it matches the Comparator interface.
But int compare(Demo2 o1, Demo2 o2) does not match this pattern. It takes two parameters. If a method accepts two parameters, it must be a static method to comply with the wrapping rules - there is no way to pass the "this" object to the Comparator interface. Therefore, it tries to wrap it as a static method and fails because it is not a static method.
Bottom line: you got an 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 notes in a comment, if you have a new class that you are building, you should not put the comparison method in it specifically for this sort of sorting task. If the class has a natural order, make it Comparable and use Arrays.sort(Object[]) . If this is not the case, and you need to sort it sometimes based on any of its attributes, use the lambda or Comparator.comparing(Demo2::getI) , which makes better use of the existing getter for the specific purpose of comparison.