Java 无法将对象添加到列表<&燃气轮机;实例化为ArrayList<;对象>;

Java 无法将对象添加到列表<&燃气轮机;实例化为ArrayList<;对象>;,java,generics,Java,Generics,我问这个问题是因为。声明如下: 给定以下代码: List<?> list =new ArrayList<Integer>(); 这会引发编译器错误,尽管我们将列表实例化为ArrayList 为什么会这样?因为列表可以是任何类型的列表(例如列表)。编译器不应该允许向列表中添加错误的类型 但是,如果您知道实际的类,则可以在运行时执行类强制转换: ((List<Integer>)list).add(e); ((列表)列表)。添加(e); 应该避免这样的代码,因

我问这个问题是因为。声明如下:

给定以下代码:

List<?> list =new ArrayList<Integer>();
这会引发编译器错误,尽管我们将列表实例化为
ArrayList

为什么会这样?

因为
列表可以是任何类型的列表(例如
列表
)。编译器不应该允许向列表中添加错误的类型

但是,如果您知道实际的类,则可以在运行时执行类强制转换:

((List<Integer>)list).add(e);
((列表)列表)。添加(e);
应该避免这样的代码,因为如果在运行时遇到意外类型,它会生成ClassCastException。更糟糕的是(如所述),我们的ClassCastException可能只发生在代码的一个完全不同的区域——即,当我们从列表中检索某些内容时

更好的方法

如果知道列表将是特定类型或该类型的超类,则可以使用有界通配符定义变量:

List<? super Integer> list;
Integer e = 2;

list = new ArrayList<Integer>();
list.add(e);

list = new ArrayList<Number>();
list.add(e);

list = new ArrayList<Object>();
list.add(e);

List只需创建一个的Arraylist,它们将允许您添加所有,因为Integer、String和Boolean是子对象,或者换句话说,Object class是其父对象。

因为您明确地从编译器获取了信息,编译器在运行时不知道实例的实际类型,它只知道您写下的类型:
List
。请注意,显示的代码不会产生
ClassCastException
,即使对于
List
,也不会产生异常-它会正常运行,仅当从列表中检索某个内容时,才可能发生
ClassCastException
。还应注意,编译器将允许向定义为
的列表中添加元素?super T
,它允许添加
T
元素或其任何超类(除非
T
是接口,您不能将
Object
添加到混合中,这一部分不起作用)。任何人都不应该做这样不安全的演员。这不是“为什么”的问题,tho。这里的问题不是要找到解决方法(我已经有了),而是要提供关于为什么会发生这种行为的信息。在回答问题时要记住这一点。
List<? super Integer> list;
Integer e = 2;

list = new ArrayList<Integer>();
list.add(e);

list = new ArrayList<Number>();
list.add(e);

list = new ArrayList<Object>();
list.add(e);