什么是<? 超T>语法?
我无法理解以下语法:
public class SortedList< T extends Comparable< ? super T> > extends LinkedList< T >
我看到类SortedList扩展了LinkedList。 我只是不知道
T extends Comparable< ? super T>
手段。
到目前为止,我的理解是,typesT必须是一个types,实现可比较…但是什么是< ? super T >
< ? super T >
?
generics中的超级是延伸的反义词。 而不是说可比较的genericstypes必须是T的一个子类,而是说它必须是T的超类。区别是非常重要的,因为扩展告诉你什么可以从一个类中得到(至less得到这个,也许是一个子类)。 super告诉你什么可以放入类(最多这个,也许是一个超类)。
在这个特定的情况下,它所说的是types必须实现自身或其超类的可比性。 所以考虑java.util.Date。 它实现了Comparable<Date>
。 但java.sql.Date呢? 它也实现了Comparable<java.util.Date>
。
如果没有超级签名,SortedList将无法接受java.sql.Date的types,因为它没有实现自身的Comparable,而是自身的超类。
这是一个下界通配符。
JLS 4.5.1types参数和通配符
通配符在只需要关于types参数的部分知识的情况下是有用的。 […]上限由语法表示:
? extends B
其中
B
是上限。 可以使用以下语法在通配符上声明下限:? super B
其中
B
是下界。
一个List<? super Integer>
例如, List<? super Integer>
包括List<Integer>
, List<Number>
和List<Object>
。
通配符用于使generics更加强大和灵活; 边界用于维护types安全。
也可以看看
- Java语言指南/generics/更多乐趣与通配符
至于在<T extends Comparable<? super T>>
<T extends Comparable<? super T>>
,这是当你有像Cat extends Animal implements Comparable<Animal>
。
看看Collections.sort
的签名
public static <T extends Comparable<? super T>> void sort(List<T> list)
因此,使用List<Cat> listOfCat
,您现在可以将Collections.sort(listOfCat)
。
如果它被宣布如下:
public static <T extends Comparable<T>> void sort(List<T> list)
那么您必须让Cat implements Comparable<Cat>
才能使用sort
。 通过使用? super T
? super T
有界通配符, Collections.sort
变得更加灵活。
也可以看看
- Effective Java第2版,第28项:使用有界通配符来增加API的灵活性
- 另外,PECS原则:“生产者
extends
消费者super
”
- 另外,PECS原则:“生产者
这意味着T
必须实现Comparable<T itself or one of T's superclasses>
。意义在于,因为SortedList
是sorting的,所以它必须知道如何比较两个类的genericsT
参数。 这就是为什么T
必须实现Comparable<T itself or one of T's superclasses>
这意味着typesT
必须实现T
Comparable
或它的一个超类。
例如,如果A
扩展B
,如果要使用SortedList<A>
,则A
必须实现Comparable<A>
或Comparable<B>
,或者实际上只是Comparable
。
这允许使用任何有效的比较器来构造A
的列表。
考虑下面的例子:
-
使用类声明中定义的types参数
公共类ArrayList扩展AbstractList … {
public boolean add(E o)//你可以在这里使用“E”,因为它已经被定义为类的一部分 -
使用类声明中未定义的types参数
public <T extends Animal> void takeThing(ArrayList<T> list) // Here we can use <T> because we declared "T" earlier in the method declaration
如果类本身不使用types参数,那么通过在返回types之前声明一个非常不寻常的(但是可用的)空间,你仍然可以为一个方法指定一个。 这个方法说T可以是“任何types的动物”。
注意:
public <T extends Animal> void takeThing(ArrayList<T> list) is NOT same as public void takeThing(ArrayList<Animal> list)
两者都是合法的,但它们是不同的。 第一个表明你可以传入一个ArrayList对象实例化为动物或任何动物子types如ArrayList,ArrayList或ArrayList。 但是,你只能在第二个传递ArrayList,而不是任何的子types。