我正在尝试学习Java泛型。我不清楚您何时使用<T extends Foo>
以及何时使用<T super Foo>
。这些事情中的每一个对T意味着什么?假设我有<T extends Comparable>
和<T super Comparable>
,这些是什么意思?
我在sun.com上看过几个教程,但我还是迷路了。有人能举例说明吗?
谢谢!
答案 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