【问题标题】:List Generics Covariance列出泛型协方差
【发布时间】:2014-03-05 00:46:51
【问题描述】:

假设我们有 2 个不同的列表。

列表 1 可以采用任何 Number 参数(包括 int、double、float 以及所有其他 Number 子类)。

 List<Number> l1 = new ArrayList();

所以这样做非常好。

    l1.add(123);
    l1.add(123.3456);

列表 2 扩展了数字。问题是我不能添加任何东西,我不明白为什么。另外,为什么我需要一个 而不是仅仅创建一个可以存储任何子类的层次结构中最高的类的列表(如列表 1)?

List<? extends Number> l2 = new ArrayList();
    l2.add(123); //Error, although Integer is a subclass of Number
    l2.add(new Integer(123)); // Wrappers don't work either
    l2.add(123.456); //Error again

【问题讨论】:

  • 查找术语 PECS(生产者扩展,消费者超级)。 Java 变体“声明”是在使用时完成的,而不是类定义时

标签: java generics covariance


【解决方案1】:

在使用? extends 通配符的类上调用具有泛型参数的方法(例如add)的问题在于编译器不知道确切的类型。它可以是List&lt;Number&gt;List&lt;Integer&gt;List&lt;Double&gt;List&lt;BigInteger&gt;。编译器必须使用泛型来保持类型安全,如果它允许这样的调用,类型安全将不会被保留。不应允许您将 Double 添加到可能是 List&lt;Integer&gt; 的列表中。

这种? extends 上限通配符本身可用作方法参数,而确切的类型并不重要;重要的是它是界限(在本例中为Number)或以下。

public void foo(List<? extends Number> list) {
    for (Number n : list) {
       // do something with some kind of Number, don't care which

【讨论】:

  • 它给出了一个编译错误默认是novariance。有什么想法吗?
【解决方案2】:

?是编译器未知的通配符。它可以是从数字派生的任何类型的类的实例。泛型是为了类型安全的确切目的而实现的,由于输入的类型是未知的,这将不起作用。

【讨论】:

    【解决方案3】:

    通配符不用于修改列表,仅用于处理列表中已包含的元素。如果您创建一个列表或向列表中添加元素,您必须知道哪些元素恰好包含在列表中。

    【讨论】:

      猜你喜欢
      • 2020-11-20
      • 2011-02-09
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多