Confused with using method reference in Comparator.comparing()

Am a self learning developer, now learning Java. I have learned that to use method reference for a Functional Interface, the signature of the method we referring must match the signature of the abstract method inside that functional interface .

But While learning Comparator, found that “Comparator.comparing()” method takes Function interface and returns a Comparator. I know that the abstract method of Function interface must take a argument and return a value.

but I can able to pass any method(as method reference) that partially (not fully) matches the signature of Function interface to the comparing() method of Comparator.

for example consider the below example.

public class Movie {
private  String title;
private int likes;

public Movie(String title, int likes) {
    this.title = title;
    this.likes = likes;
}

public String getTitle(){
    return title;
}

public int getLikes() {
    return likes;
}
}

import java.util.Comparator;
import java.util.List;

public class Main {
public static void main(String[] args) {     
    var movies=List.of(
      new Movie("b", 20),
      new Movie("c", 30),
      new Movie("a", 10));

    var stream=movies.stream().
    sorted(Comparator.comparing(Movie::getTitle));  
    stream.forEach(m->System.out.println(m.getLikes()));
  }
}

Here, in the line "sorted(Comparator.comparing(Movie::getTitle))"

as you see the getTitle() method takes no argument and returns a String value . But it can be used as method reference for the function interface (which takes a argument and returns a value) .

Why is it happening ? Please answer anyone to solve my confusion.

When you use a static method reference, it works exactly as you described, but when you use an instance method reference, it has an implied argument (the instance of the class). So the method reference there is actually more like this if written as a lambda: movie -> movie.getTitle(). That would have the type Function<Movie, String>.

In the case where the method already has one or more parameters, it gets added as an additional parameter (the first parameter to be more specific). For example, String::charAt would resolve to (str, index) -> str.charAt(index) which is a BiFunction<String, Integer, Character>.

Oracle has a more comprehensive tutorial about all of the different types of method references:

NOTE: Movie::getTitle is a “Reference to an Instance Method of an Arbitrary Object of a Particular Type”.

1 Like