泛型 - 无法添加到具有无界通配符的列表

时间:2012-03-09 16:01:24

标签: java generics

我实例化以下列表:

// I am just revising generics again and the following is just cursory code!
List<? super Integer> someList = new ArrayList<Object>();
someList.add(new Object());

以上不起作用。我收到编译器错误。但是,以下工作:

List<? super Integer> someList = new ArrayList<Object>();
someList.add(11);

我知道您可以将对象添加到包含无界通配符的集合中,而不是有界通配符。

但是,为什么以上不起作用? Object是Integer的超类型,为什么我不能添加它呢?

4 个答案:

答案 0 :(得分:6)

它声明它是一个超类型的东西的列表,而不是列表可以包含任何超类型的整数。换句话说,对于编译器,它可以是List<Integer>List<Number>List<Object>,但它不知道哪个,所以你不能添加任何东西到名单。你唯一可以安全添加的是Integer,因为它保证是List可能拥有的任何类型的子类型。

换句话说,?代表一个类型,而不是任何类型。这是一个非显而易见但重要的区别。

答案 1 :(得分:4)

对于变量someList,所有编译器/语言必须使用的是静态类型List<? super Integer>。它可能是从List<Integer>分配的。显然,您不希望将new Object()添加到List<Integer>

您可以将null添加到List<? super Integer>,然后您可以将列表传递给另一种捕获泛型类型的方法,因此可以在列表周围移动引用(方法,如Collections.shuffle )。

答案 2 :(得分:1)

List<? super Integer>不是包含任何超类型Integer的任何元素的列表(这也没有意义),但列表是具体的未知元素类型,它是{{1的超类型}}。因此编译器没有机会确定要添加的元素是否具有正确的具体类型。

元素类型中带有通配符的任何集合本身都不可扩展,但它们是可修改的(您可以删除元素或清除整个列表)。

答案 3 :(得分:1)

当编译器点击someList.add(new Object())时,它不记得你如何实例化someList。编译器的所有信息都是someList的声明方式,即List<? super Integer> someList。由于您可以通过

实例化someList
someList = new ArrayList<Object>()

someList = new ArrayList<Integer>()

并且编译器不知道它是哪一个,因此编译器不允许您执行someList.add(new Object()),因为someList可能是List<Integer>

相关问题