【问题标题】:List<? super List<? super Integer>> and List<? extends List<? super Integer>> and how to use it correctly?列表<?超级列表<?超级整数>>和列表<?扩展列表<? super Integer>> 以及如何正确使用?
【发布时间】:2021-12-15 02:59:25
【问题描述】:

考虑以下 sn-p:

List<Double> doubleList = null;
List<Integer> integerList = null;
List<Number> numberList = null;

//expression:1
List<? super List<? super Integer>> superDoubleList = Arrays.asList(doubleList, integerList,numberList);

//expression:2
//here doubleList will cause compilation error
List<? extends List<? super Integer>> extendsDoubleList = Arrays.asList(integerList,numberList);//doubleList
  • 在这里,我试图了解如何解释这两个语句
    • 表达式:1
      • 这里我们说 RHS 上的列表必须是列表的所有元素都满足条件? super List&lt;? super Integer&gt;
      • 但是 doubleList / integerList / numberList 无论如何都不能满足这个条件 - 因为我们期望一个类型是 List&lt;? super Integer&gt; 的超类型。
      • 为什么这里没有编译错误?
    • 表达式:2
      • 这里我们期望 RHS 上的元素必须是 subtype of List&lt;? super Integer&gt;
      • 所以doubleList直观上可以看成是可以满足条件的候选人。
      • 如果我在Arrays.asList 表达式中包含doubleList,为什么仍然会出现编译错误?

不确定我是否以正确的方式解释了这些表达式 - 从逻辑上讲它似乎不符合我上面给出的解释可能有什么问题?

【问题讨论】:

  • 与其考虑超类型和子类型,不如将? super? extends 考虑为consumers and producers,这样更容易推理。
  • 我没有收到编译器错误。用JDK8、JDK11、JDK17测试。所以我投票决定关闭。
  • @Seelenvirtuose 您需要(我引用)“在Arrays.asList 表达式中包含doubleList”以获取编译器错误。
  • @Sweeper Arrgh。我的错。过失。

标签: java generics jls bounded-wildcard unbounded-wildcard


【解决方案1】:

编译的两种情况,编译是因为类型推断算法尽力推断asList调用的类型参数以使您的代码编译。这与三个列表的类型无关(它们只是间接相关)。这完全取决于Arrays.asList 返回的类型。

第一种情况:

List<? super List<? super Integer>> superDoubleList = Arrays.asList(doubleList, integerList,numberList);

要编译您的代码,Arrays.asList,只需创建一个List&lt;List&lt;?&gt;&gt;。毕竟这三个列表都是“something的列表”,所以这是可能的。

List&lt;List&lt;?&gt;&gt;List&lt;? super List&lt;? super Integer&gt;&gt; 的一种。这是因为List&lt;?&gt;List&lt;? super Integer&gt; 的超类型——“a list of some Integer supertype”是一种“a list of some objects”。

对此的另一种解释是将? super T 视为“T 的消费者”,将? extends T 视为“T 的生产者”。 (PECS) 在这种解释中,List&lt;? super List&lt;? super Integer&gt;&gt; 的意思是“可以使用 可以使用 整数的列表”。列表上下文中的“使用”仅表示“添加”。包含doubleListintegerListnumberList 的列表可以做到这一点吗?当然,无论列表的内容是什么,您都可以随时将另一个List&lt;? super Integer&gt; 添加到列表中。只是列表的type 必须是List&lt;List&lt;?&gt;&gt;。即使这样也有效:

List<? super List<? super Integer>> superDoubleList =
    Arrays.asList(new ArrayList<String>(), new ArrayList<LocalDate>());

使用相同的解释,List&lt;? extends List&lt;? super Integer&gt;&gt; 表示“可以产生列表使用整数的列表”。可以

Arrays.asList(integerList,numberList)

这样做?是的,这两个内部列表都可以使用整数,因此外部列表可以“生成使用整数的列表”,或者换句话说,是此类列表的生产者

这个列表列表怎么样?

Arrays.asList(doubleList,integerList,numberList)

它是可以消费整数的列表的生产者吗?嗯,不,因为doubleList 不消耗整数,但它可以产生。

您可能想知道在这种情况下 Java 编译器为 asList 推断出的类型是什么:

List<? extends List<? super Integer>> extendsDoubleList = Arrays.asList(integerList,numberList);

asList 可以创建一个List&lt;List&lt;? super Integer&gt;&gt;。然而,实际推断出的类型似乎是别的东西,它不能用 Java 的语法来表达。

【讨论】:

    猜你喜欢
    • 2010-12-26
    • 2010-10-17
    • 1970-01-01
    • 2013-09-16
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    相关资源
    最近更新 更多