【问题标题】: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 上阅读了几篇教程,但我仍然迷路。有人可以举例说明吗?

【问题讨论】:

标签: java generics


【解决方案1】:

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

<T extends Parent> 接受 Parent 或 Child,而 <T super Parent> 接受 Parent 或 Grandparent。

【讨论】:

  • 这是我见过的这个问题的最佳答案,应该是公认的答案。简单而完美。
  • 所以它更像是向下继承(扩展)或向上继承(超级)
  • 接受 Parent 或 Grandparent,但是 Child 呢?我只是尝试添加,它接受了
  • "<T super Parent> 接受父母或祖父母" - 和Object,对吗?
【解决方案2】:

通配符分为三种:

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

【讨论】:

【解决方案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。我在这里继续,文章的结论。

使用列表super Suit> 每当您要写入 到列表中。

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

使用列表extends Suit> 每当您要从列表中读取

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

【讨论】:

    【解决方案5】:

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

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

    在这种情况下,如果您看到MyClass&lt; ConcreteT &gt;,则必须将 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-24
        • 2018-11-20
        • 2011-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-23
        相关资源
        最近更新 更多