【问题标题】:What is <? super T> syntax? [duplicate]什么是<?超级 T> 语法? [复制]
【发布时间】:2010-05-13 14:28:39
【问题描述】:

我无法理解以下语法:

public class SortedList< T extends Comparable< ? super T> > extends LinkedList< T >

我看到 SortedList 类扩展了 LinkedList。我只是不知道是什么

T extends Comparable< ? super T>

意思。

目前我对它的理解是,类型 T 一定是实现了 Comparable 的类型……但是&lt; ? super T &gt; 是什么?

【问题讨论】:

    标签: java


    【解决方案1】:

    泛型中的super与extends相反。不是说可比较的泛型类型必须是 T 的子类,而是说它必须是 T 的超类。区别很重要,因为 extends 告诉您可以从类中得到什么(您至少会得到这个,也许是一个子类)。 super 告诉你你可以在类中加入什么(最多这个,也许是一个超类)。

    在这种特定情况下,它的意思是该类型必须实现其自身或其超类的可比较性。所以考虑 java.util.Date。它实现了Comparable&lt;Date&gt;。但是 java.sql.Date 呢?它也实现了Comparable&lt;java.util.Date&gt;

    如果没有 super 签名,SortedList 将无法接受 java.sql.Date 的类型,因为它没有实现自身的 Comparable,而是实现了自身的超类。

    【讨论】:

    • 我明白了。那么给定那个类, Collection list = new SortedList();是一个有效的陈述?
    • @aloh,不会因为 Object 没有实现 Comparable。
    • 对不起,我知道这个问题有点老了,但是如果我们改为写Comparable&lt;? extends T&gt;,我们能说些什么。这意味着什么以及为什么代码无法编译?
    • @tonix 在这种情况下我们说的是那种类型?必须是该泛型类型 T 的子类,例如如果我们说 T 是数字,那么?必须是 Integer、Double、Short 等
    【解决方案2】:

    这是一个下界通配符。

    JLS 4.5.1 Type Arguments and Wildcards

    通配符在只需要部分了解类型参数的情况下很有用。 [...] 上限由以下语法表示:

    ? extends B
    

    其中B 是上限。 [...] 可以使用以下语法在通配符上声明下限:

    ? super B
    

    其中B 是一个下限。

    例如,List&lt;? super Integer&gt; 包括 List&lt;Integer&gt;List&lt;Number&gt;List&lt;Object&gt;

    通配符用于使泛型更加强大和灵活;边界用于维护类型安全。

    另见


    至于这对&lt;T extends Comparable&lt;? super T&gt;&gt; 有什么用处,那就是当你有类似Cat extends Animal implements Comparable&lt;Animal&gt; 的东西时。

    Collections.sort的签名

    public static <T extends Comparable<? super T>> void sort(List<T> list)
    

    因此,使用List&lt;Cat&gt; listOfCat,您现在可以Collections.sort(listOfCat)

    是否声明如下:

    public static <T extends Comparable<T>> void sort(List<T> list)
    

    那么您必须拥有Cat implements Comparable&lt;Cat&gt; 才能使用sort。通过使用? super T 有界通配符,Collections.sort 变得更加灵活。

    另见

    • Effective Java 2nd Edition,Item 28:使用有界通配符来提高 API 灵活性
      • 还有,PECS 原则:“生产者extends消费者super

    【讨论】:

    • 这比这要复杂一些——问题不是关于? super T,而是关于T extends Comparable&lt;? super T&gt;
    • 啊,我明白了。这些都实现了 Comparable。 super 关键字呢?
    • 不是真的!如果您查看文档,您会发现它不仅仅是一个有界通配符。
    • 为了澄清,我之前的评论是针对您最初的回复,只有 3-4 行。
    • 这是一个比公认答案更清晰的世界......
    【解决方案3】:

    表示T必须实现Comparable&lt;T itself or one of T's superclasses&gt; 感觉是因为SortedList是排序的,它必须知道如何比较其泛型T参数的两个类。这就是为什么T必须实现Comparable&lt;T itself or one of T's superclasses&gt;

    【讨论】:

      【解决方案4】:

      这意味着T类型必须实现TComparable或其超类之一。

      例如,如果A扩展B,如果你想使用SortedList&lt;A&gt;A必须实现Comparable&lt;A&gt;Comparable&lt;B&gt;,或者实际上只是Comparable

      这允许使用任何有效的比较器构造As 列表。

      【讨论】:

        【解决方案5】:

        考虑以下示例:

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

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

        2. 使用未在类声明中定义的类型参数

          public <T extends Animal> void takeThing(ArrayList<T> list)
                                                      // Here we can use <T> because we declared "T" earlier in the method declaration                  
          

          如果类本身不使用类型参数,您仍然可以为方法指定一个,方法是在一个非常不寻常(但可用)的空间中声明它 - 在返回类型之前。这个方法说 T 可以是“任何类型的动物”。

        注意:

        public <T extends Animal> void takeThing(ArrayList<T> list)             
        
        is NOT same as              
        
        public void takeThing(ArrayList<Animal> list)
        

        两者都是合法的,但它们是不同的。第一个表示您可以传入实例化为 Animal 或任何 Animal 子类型(如 ArrayList、ArrayList 或 ArrayList)的 ArrayList 对象。但是,您只能在第二个中传递 ArrayList,而不是任何子类型。

        【讨论】:

          猜你喜欢
          • 2014-07-28
          • 1970-01-01
          • 1970-01-01
          • 2015-07-21
          • 1970-01-01
          • 2013-07-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多