Java Generics中'super'和'extends'之间的区别是什么?

时间:2009-12-15 22:30:19

标签: java generics

我正在尝试学习Java泛型。我不清楚您何时使用<T extends Foo>以及何时使用<T super Foo>。这些事情中的每一个对T意味着什么?假设我有<T extends Comparable><T super Comparable>,这些是什么意思?

我在sun.com上看过几个教程,但我还是迷路了。有人能举例说明吗?

谢谢!

6 个答案:

答案 0 :(得分:269)

它取决于它允许的继承层次结构。假设你有一个继承自“祖父母”继承自“父母”的班级“孩子”。

<T extends Parent>接受父母或子女,<T super Parent>接受父母或祖父母。

答案 1 :(得分:15)

通配符有三种类型:

  • ? extends Type:表示Type类型的一系列子类型。这是最有用的通配符。
  • ? super Type:表示Type类型的超类型系列。
  • ?:表示所有类型或任何类型的集合。

答案 2 :(得分:15)

参见Effective Java 2nd Edition,Item 28:

<强> PECS

P roducer e xtends, C onsumer s uper

如果您的参数是生产者,则它应为<? extends T>,如果它是消费者,则必须为<? super T>

看一下Google Collections,他们知道如何使用它,因为他们有Bloch;)

答案 3 :(得分:13)

对我来说,最好的答案来自@BSingh,当我读到鲍勃叔叔的文章时。我在这里继续,文章的结论。

使用清单&lt; T 超级套装&gt;每当你打算到列表中时。

  

当您将一个Object放入List时,您所关心的只是该对象的类型与列表所拥有的类型兼容。因此,您希望列表采用该对象的类型或该对象的任何超类。

使用清单&lt; T 延伸套装&gt;无论何时从列表中读取

  

另一方面,当您从列表中读取时,您希望您正在阅读的类型是列表中包含的类型,或者是该类型的派生类型。

答案 4 :(得分:4)

如果您询问类型参数,那么Java中没有<T super X>构造。有界参数只能extend,但它可以扩展多个类型。 E.g

public class MyClass< T extends Closeable & Runnable >
{
  // Closeable and Runnable are chosen for demonstration purposes only
}

在这种情况下,如果您看到MyClass< ConcreteT >,则必须将ConcreteT声明为

public class ConcreteT
  implements Closeable, Runnable
{
   ...
}

对于有界通配符,请阅读this article。阅读获取原则部分。基本上,super对应write语义,extends对应read语义。

答案 5 :(得分:2)

记住PECS - Producer扩展消费者支持。此外,鲍勃叔叔在他的工匠系列中也很好地讨论了它。查看http://objectmentor.com/resources/articles/The_Craftsman_44__Brown_Bag_I.pdf