Java泛型中的“超级”和“扩展”有啥区别[重复]
Posted
技术标签:
【中文标题】Java泛型中的“超级”和“扩展”有啥区别[重复]【英文标题】:What is the difference between 'super' and 'extends' in Java Generics [duplicate]Java泛型中的“超级”和“扩展”有什么区别[重复] 【发布时间】:2010-12-27 00:32:37 【问题描述】:我正在尝试学习 Java 泛型。我不清楚你什么时候使用<T extends Foo>
,什么时候使用<T super Foo>
。这些事情中的每一件事对 T 意味着什么?假设我有<T extends Comparable>
和<T super Comparable>
,它们分别是什么意思?
我在 sun.com 上阅读了几篇教程,但我仍然迷路。有人可以举例说明吗?
【问题讨论】:
这个问题之前已经讨论过了 - 见***.com/questions/1368166/…和***.com/questions/252055/java-generics-wildcards和***.com/questions/1906677/… (注意Comparable
是一个泛型类型,所以在泛型绑定中使用它作为原始类型会导致痛苦。它应该,最“简单”是Comparable<?>
。)跨度>
没有“这取决于它允许的继承层次结构。假设你有一个继承自“祖父母”的“父母”的“孩子”类。
<T extends Parent>
接受 Parent 或 Child,而 <T super Parent>
接受 Parent 或 Grandparent。
【讨论】:
这是我见过的这个问题的最佳答案,应该是公认的答案。简单而完美。 所以它更像是向下继承(扩展)或向上继承(超级)<T super Parent>
接受父母或祖父母" - 和Object
,对吗?【参考方案2】:
通配符分为三种:
? extends Type
:表示Type
类型的子类型族。这是最有用的通配符。
? super Type
:表示Type
类型的超类型族。
?
:表示所有类型或任何类型的集合。
【讨论】:
仅供参考:这是从java.sun.com/developer/technicalArticles/J2SE/generics 中提取的,以后请提及您的来源,而不是写得好像它们是您的一样。 @BalusC 的文章链接不再有效。这是当前的一个:oracle.com/technetwork/articles/javase/generics-136597.html【参考方案3】:参见 Effective Java 第 2 版,第 28 条:
PECS
P生产者extends,C消费者s上层
如果你的参数是生产者,它应该是<? extends T>
,如果是消费者,它必须是<? super T>
。
看看 Google Collections,他们知道如何使用它,因为他们有 Bloch ;)
【讨论】:
这并不能真正解释它们的工作原理或含义,而 R Samuel Klatchko's answer 可以。 不明白,不解释区别。 Bloch 是这样解释的:假设你想将批量方法添加到Stack<E>
: •void pushAll(Collection<? extends E> src);
•void popAll(Collection<? super E> dst);
• 用户可以 i> pushAll
从一个 Collection<Long>
或一个 Collection<Number>
到一个 Stack<Number>
• 用户可以 popAll
进入一个 Collection<Object>
或一个 Collection<Number>
来自一个 Stack<Number>
制片人?消费者?请解释。你没有回答问题。
很高兴你喜欢引用 Effective Java 2nd Edition,但作者已经提到他已经搜索过,暗示他已经看到了。无论如何,他的问题不是何时使用 super vs extends,而是它们的实际含义。这意味着他正在寻找两者之间的机械差异,以了解“为什么”使用而不是“何时”使用。这个答案充其量是切题的,但我认为它与问题完全无关。【参考方案4】:
当我阅读鲍勃叔叔的文章时,对我来说最好的答案来自@BSingh。我在这里继续,文章的结论。
使用列表
当您将一个对象放入列表时,您所关心的只是该对象的类型是否与列表所包含的类型兼容。因此,您希望列表采用该对象的类型或该对象的任何超类。
使用列表
另一方面,当您从列表中读取数据时,您希望正在读取的类型是列表中包含的类型,或者是该类型的派生类型。
【讨论】:
【参考方案5】:如果您询问类型参数,那么 Java 中没有 <T super X>
构造。有界参数只能extend
,但可以扩展多个类型。例如
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。阅读get-put 原则部分。基本上super
对应write
语义,extends
对应read
语义。
【讨论】:
【参考方案6】:记住 PECS - 生产者扩展消费者支持。此外,鲍勃叔叔在他的工匠系列中对此进行了很好的讨论。查看http://objectmentor.com/resources/articles/The_Craftsman_44__Brown_Bag_I.pdf
【讨论】:
以上是关于Java泛型中的“超级”和“扩展”有啥区别[重复]的主要内容,如果未能解决你的问题,请参考以下文章