在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