列表<?超级列表<?超级整数>>和列表<?扩展列表 <? super Integer>> 以及如何正确使用它?

List<? super List<? super Integer>> and List<? extends List<? super Integer>> and how to use it correctly?

考虑以下片段:

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

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

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

的类型

第一种情况:

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

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

List<List<?>>List<? super List<? super Integer>>的一种。这是因为 List<?>List<? super Integer> 的超类型 - “一些 Integer 超类型的列表”是一种“一些对象的列表”。

对此的另一种解释是,将 ? super T 视为“T 的消费者”,将 ? extends T 视为“T 的生产者”。 (PECS) 在此解释中,List<? super List<? super Integer>> 表示“可以 消耗的列表 可以 消耗 整数的列表”。列表上下文中的“消费”仅表示“添加”。包含 doubleListintegerListnumberList 的列表可以做到这一点吗?当然,不管列表的内容是什么,您总是可以向列表中添加另一个 List<? super Integer>。只是列表的类型必须是List<List<?>>。即使这样也有效:

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

使用相同的解释,List<? extends List<? super Integer>> 意思是“一个列表可以 产生 列出 使用 整数”。可以

Arrays.asList(integerList,numberList)

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

这个列表列表怎么样?

Arrays.asList(doubleList,integerList,numberList)

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

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

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

asList 可以创建 List<List<? super Integer>>。然而,实际的推断类型似乎是其他东西,无法用 Java 的语法表达。