• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Junilu Lacar
  • Martin Vashko
  • Jeanne Boyarsky
  • Tim Cooke
  • Knute Snortum
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Scott Selikoff
  • salvin francis
  • Piet Souris

Need clarification on method declaration - comparing in Comparator interface

Ranch Hand
Posts: 124
jQuery Eclipse IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

I was reading the book OCP written by Jeanne.

I saw a method declared as follows:

In the book I see the statement as :

I dont really understand completely about the method comparing declaration.

I know that function takes input of type T and returns of type R. Here the input is Squirrel (input parameter is of Squirrel) type and return type is String (s.getSpecies() is a String)

As far as i know, generic static method can be written as : public static <T> Comparator<T> comparing(.......). Correct me if i am wrong.

But instead of public static <T> Comparator<T> , i found public static <T, R extends Comparable<? super R>> Comparator<T>. I am not clear why the method is llike this.

Thanks & Regards,


Posts: 66575
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I presume you mean the OCP8 book by Jeanne Boyarsky and Scott Selikoff.

I know a resource for such strange‑looking generics. Ken Kousen's book Modern Java Recipes (O'Reilly 2017) (Amazon link). Comparator#comparing appears on pages 267 and 280.
Where did you find that method declaration? Was it here? If so, let's see if we can't tease it apart. The method takes one parameter which is a Function<T, U>. so let's have a look at the Function.
The apply() method takes a T and returns an R, only the comparing() method declaration calls that U. So, in the current example, a Squirrel is the T. The λ goes from T=Squirrel to U/R=species, but you can see from the declaration that U/R must implement Comparable. It actually says R extends Comparable<? super R> because:-
  • 1: Comparable is itself parametrised
  • 2: The class actually implementing Comparable<T> might be a superclass of the current R/U.
  • In this case you are going from Squirrel (=T) to species (=R/U) which must implement Comparable. Maybe species is a String. So you now have a Function<Squirrel, (??)String>.
    So far so good. What the function does is allows the Comparator to extract some information from the Squirrel object that it can use for comparisons. Now it has extracted that information, it can return a Comparator reference which uses species for comparisons.
    You could also pass a method reference because all that λ is doing is calling a certain method: Squirrel::getSpecies. That might look like calling a static method but it isn't. It means the Squirrel reference is passed to the left half of the method reference and the right half is then called on that reference.
    Saloon Keeper
    Posts: 10873
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It's because the method needs two generic type parameters: not just T for the type of objects to be compared, but also R, for the type of objects that will REALLY be compared on T's behalf.

    Normally you would then start declaring the generic method as:

    The problem with this is the implementation of the method. In order to compare squirrels by species, the species itself must be comparable:

    To make it work, R must be declared as being comparable:

    This will compile, and you can call it just fine with Squirrel::getSpecies, but the following perfectly reasonable program won't compile:

    Line 14 of BananaMilkshake won't compile, because T is BananaMilkshake, R is Banana and a Banana is a Comparable<Fruit>, while R is required to be a Comparable<Banana>.

    The reason for this is that our declaration of comparing() didn't specify type bounds on its generic parameters. If R is a Banana, we want the method to treat it as a Comparable<Fruit>:

    For similar reasons, we also specify generic type bounds on the keyExtractor parameter:
    Swapna latha
    Ranch Hand
    Posts: 124
    jQuery Eclipse IDE
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:It's because the method needs two generic type parameters: . . .

    Thank you very much Stephan.
    I am not young enough to know everything. - Oscar Wilde This tiny ad thinks it knows more than Oscar:
    Java file APIs (DOC, XLS, PDF, and many more)
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!