The Java PriorityQueue source code defined in jdk8 uses a comparator defined like this
/**
* The comparator, or null if priority queue uses elements'
* natural ordering.
*/
private final Comparator<? super E> comparator;
Source code here (line 108)
Why the need for using a type that is super of E and not simply E.
In other words, why not define the comparator just like below:
private final Comparator<E> comparator;
What is the motivation behind that extra abstraction?
CodePudding user response:
Because why not.
Given a comparator that can compare any 2 CharSequence objects (CharSequence is an interface; String, StringBuilder, and a few other things implement it), then.. that is just as good when you have a need to compare only strings. All Strings are also CharSequences, so a comparator that can tell you for any 2 charsequence objects which one 'comes first' can do the job perfectly well.
Generics are invariant by default, so if you have a PriorityQueue<String>
, and it worked like you want to, it'd look like Comparator<E>
, which means Comparator<String>
, and a Comparator<CharSequence>
is not compatible with that. Like passing a String
to a method that wants an Integer
object, it just doesn't compile.
Hence, <? super E>
so that you can pass a Comparator<CharSequence>
.
It doesn't come up often, of course, but it's 'more correct' this way. I'm sure you'd be surprised if you so happen to have a comparator of CharSequences laying about and can't use it to power a PriorityQueue<String>
.