在Javagenerics中“超级”和“扩展”有什么区别
我正在尝试学习Javagenerics。 我不清楚什么时候你会用<T extends Foo>
和什么时候用<T super Foo>
。 这些东西对T来说意味着什么? 假设我有<T extends Comparable>
和<T super Comparable>
,这些都是什么意思?
我已经在sun.com上看了几篇教程,但是我还是输了。 有人可以用例子来说明吗?
谢谢!
请参阅Effective Java第2版,第28项:
佩奇
产品代码, C onsumer sper
如果你的参数是一个生产者,它应该是<? extends T>
<? extends T>
,如果它是一个消费者,它必须是<? super T>
<? super T>
。
看看Google Collections,他们知道如何使用它,因为他们得到了Bloch;)
它依赖于它允许的inheritance层次结构。 假设你有一个从“祖父母”inheritance的“父”inheritance的类“孩子”。
<T extends Parent>
接受Parent或Child,而<T super Parent>
接受Parent或者祖父母。
有三种通配符:
-
? extends Type
? extends Type
:表示一系列types为Type
的子Type
。 这是最有用的通配符。 -
? super Type
? super Type
:表示types为Type
的超types族。 -
?
:表示所有types或任何的集合。
对我来说,最好的答案来自@BSingh,当我读到Bob叔叔的文章时。 我在这里重申文章的结论。
每当你要写入列表时,使用List <T super Suit>。
当你把一个对象放到列表中时,你所关心的只是该对象是一个与列表所持有的types兼容的types。 所以你想要列表采取该对象的types或该对象的任何超类。
每当你要从列表中读取 ,使用List <T extends Suit>。
另一方面,当你从列表中读取时,你希望你正在阅读的types是列表中包含的types,或者是该types的派生types。
如果你问的是types参数,那么Java中就没有<T super X>
结构。 有界参数只能extend
,但可以扩展多个types。 例如
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 { ... }
对于有界的通配符,阅读这篇文章 。 阅读关于获取原则的部分 。 基本上, super
对应于write
语义, extends
对应于read
语义。
记住PECS – 生产者扩大消费者支持。 另外,鲍伯叔叔在他的工匠系列中对它进行了很好的讨论。 看看resources/articles/The_Craftsman_44__Brown_Bag_I.html