【问题标题】:What's the difference between these generic declarations?这些通用声明之间有什么区别?
【发布时间】:2014-06-16 19:14:35
【问题描述】:

您会如何用简单的英语描述这些列表内容之间的区别?

我正在寻找可以作为参考的简单比较。

/* 1 */ List<          List<          Dog>>
/* 2 */ List<          List<? extends Dog>>
/* 3 */ List<? extends List<          Dog>>
/* 4 */ List<? extends List<? extends Dog>>

super 的泛型声明类似。那么这些呢:

/* 5 */ List<? super   List<? extends Dog>>
/* 6 */ List<? extends List<? super   Dog>>

相关问题和资源

【问题讨论】:

标签: java generics nested-generics


【解决方案1】:
  1. List,其元素是狗列表
  2. 一个List,其元素是extends Dog 类型的列表
  3. List,其元素是狗列表的单个子类型
  4. 一个List,其元素是一个单个子类型(extends Dog的类型列表)
  5. 一个List,其元素是一个单个超类型(extends Dog的类型列表)
  6. 一个List,其元素是一个(super Dog 的类型列表)的单个子类型

其中“subtype”、“supertype”、“super”和“extends”是“通用”版本(即也包括边界类型)


Number 和子类型的示例,因为为什么不呢。将Dog 替换为Number

  1. List&lt;List&lt;Number&gt;&gt; 可能看起来像 Number 元素的二维数组。很简单。

  2. List&lt;List&lt;? extends Number&gt;&gt; 可能看起来像一个二维数组,其中每一行都是数字的不同子类型。例如,第一行可能是List&lt;Integer&gt;,第二行可能是List&lt;Double&gt;,等等。

  3. List&lt;? extends List&lt;Number&gt;&gt; 可能是 List&lt;ArrayList&lt;Number&gt;&gt;List&lt;List&lt;Number&gt;&gt;List&lt;LinkedList&lt;Number&gt;&gt; 等。Number 必须保留,因为泛型是不变的,但您可以使用 List 或其任何一个子类型作为元素的“整体”类型。不过你只能选择List 或其子类型之一,而你选择的那个你必须留下来。

  4. List&lt;? extends List&lt;? extends Number&gt;&gt; 类似于List&lt;? extends List&lt;Number&gt;&gt;,不同的是现在您可以选择Number 或其任何子类作为“整体”二维数组的元素。所以你可以有List&lt;List&lt;Integer&gt;&gt;List&lt;ArrayList&lt;Integer&gt;&gt;List&lt;LinkedList&lt;Double&gt;&gt;等。和以前一样,你只能选择List的子类型之一和Number的子类型之一。

  5. 棘手!List&lt;? super List&lt;? extends Number&gt;&gt; 似乎等同于 List&lt;List&lt;? extends Number&gt;&gt;List&lt;Collection&lt;? extends Number&gt;&gt; 等,但 List&lt;List&lt;Number&gt;&gt; 或任何具体的子类型使用Number。我认为这是因为List&lt;Number&gt; 不被视为List&lt;? extends Number&gt; 的超类型,我认为这是有道理的,因为泛型是不变的。 List&lt;Object&gt; 以及原始类型(List&lt;List&gt;List&lt;Collection&gt; 等)也可以。
  6. 与 4 相同,只是您将 List&lt;Number&gt;List&lt;Object&gt;(显然是 List&lt;Serializable&gt;)作为内部列表。

正如@MadProgrammer 所说,由于PECS(Producer-Extends-Consumer-Super),任何时候您的泛型类型都有? extends,您将无法更新列表,只能从中检索项目。所以没有add()-ing,也没有set()-ing。

【讨论】:

  • 还要考虑到最后两个不会让你更新列表,第二个也不会让你更新子列表
  • 绝妙的答案!请看后续问题
  • @MBlanc 刚刚做了。仍在计算 5,但我认为我得到了其他一切。感谢您的脑筋急转弯!
  • @MBlanc 你知道,我在 Eclipse 中得到了一些真的奇怪的东西。当我使用&lt;&gt; 让Eclipse 找出final List&lt;? super List&lt;? extends Number&gt;&gt; a = new ArrayList&lt;&gt;(); 的边界时,它说ArrayList 的类型是ArrayList&lt;List&lt;? extends Number&gt;&gt;。但实际上写ArrayList&lt;List&lt;Number&gt;&gt; 是编译器错误。所以很明显 也不明白什么...
  • @MBlanc 好吧,我认为我搞定了一切。希望我的逻辑是有道理的。如果我有任何问题或需要进一步解释,请告诉我。
【解决方案2】:

第一个是具体的:它是Lists 的DogList,仅此而已。

第二个是最内层声明的抽象:它是从Dog 继承的某个类的Lists 的List——比如Poodle。可能是List&lt;ArrayList&lt;Poodle&gt;&gt;

第三个是内部列表声明的抽象:它是某种容器的List,它继承自List——也许是ArrayList——Dog。那么你可能有List&lt;ArrayList&lt;Dog&gt;&gt;

第四个是两者的抽象:它是从List 派生的某种容器的List,里面装满了从Dog 继承的某种动物——也许是List&lt;ArrayList&lt;Poodle&gt;&gt;

【讨论】:

    【解决方案3】:

    将每个“

    只要有“? extends X”,就在 X 之后插入“或其子类之一”。

    【讨论】:

      猜你喜欢
      • 2015-12-14
      • 2014-04-10
      • 2010-09-18
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多