什么是<? 超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

这意味着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的列表。

考虑下面的例子:

  1. 使用类声明中定义的types参数

    公共类ArrayList扩展AbstractList … {
    public boolean add(E o)//你可以在这里使用“E”,因为它已经被定义为类的一部分

  2. 使用类声明中未定义的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。