I noticed the specificaition for Collections.sort:
public static <T> void sort(List<T> list, Comparator<? super T> c)
Why is the " ? super
" necessary here? If ClassB
extends ClassA
, then wouldn't we have a guarantee that a Comparator<ClassA>
would be able to compare two ClassB
objects anyway, without the " ? super
" part?
In other words, given this code:
List<ClassB> list = . . . ;
Comparator<ClassA> comp = . . . ;
Collections.sort(list, comp);
why isn't the compiler smart enough to know that this is OK even without specifying " ? super
" for the declaration of Collections.sort()?
Josh Bloch had a talk at Google I/O this year, called Effective Java Reloaded , which you may find interesting. It talks about a mnemonic called "Pecs" (producer extends
, consumer super
), which explains why you use ? extends T
? extends T
and ? super T
? super T
in your input parameters (only; never for return types), and when to use which.
在使用通配符更有趣的情况下,有一个非常好(但有点曲折)的解释。
This is similar to C#, I just learned about it a couple days ago as to why (the hard way, and then the PDC informative way).
Assume Dog extends Animal
Blah<Dog>
is not the same as Blah<Animal>
they have completely different type signatures even though Dog
extends Animal
.
For example assume a method on Blah<T>
:
T Clone();
In Blah<Dog>
this is Dog Clone();
while in Blah<Animal>
this is Animal Clone();
.
You need a way to distinguish that the compiler can say that Blah<Dog>
has the same public interface of Blah<Animal>
and that's what <? super T>
<? super T>
indicates - any class used as T can be reduced to its super class in terms of Blah<? super T>
Blah<? super T>
.
(In C# 4.0 this would be Blah<out T>
I believe.)
It's obvious to you that, in the case of Comparator
, any ancestor of T
would work. But the compiler doesn't know that class Comparator
functions like that - it just needs to be told whether it should allow <T>
or <? super T>
<? super T>
.
Viewed another way, yes it's true that any Comparator
of an ancestor would work in this case - and the way the library developer says that is to use <? super T>
<? super T>
.
The simple answer to your question is that the library designer wanted to give the maximum flexibility to the user of the library; this method signature for example allows you to do something like this:
List<Integer> ints = Arrays.asList(1,2,3);
Comparator<Number> numberComparator = ...;
Collections.sort(ints, numberComparator);
Using the wildcard prevents you from being forced to use a Comparator<Integer>
; the fact that the language requires a wildcard to be specified by the library designer enables him or her to either permit or restrict such use.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.