为什么在将对象类型更改为泛型后,我仍然能够将任何对象添加到具有原始类型引用类型的列表中?

Why am I still able to add any Object to a List with a raw-type reference type after changing its object type to a generic?

我使用 List 的原始引用类型和 ArrayList 的原始对象类型声明并初始化了 myList。然后,我将 myList 重新引用到一个新的、通用的 Longs ArrayList。我认为向这个列表中添加 Long 以外的任何东西都会导致错误。

List myList = new ArrayList();
myList = new ArrayList<Long>();
myList.add(3.4d);
myList.add(4.0f);
myList.add("weird");
myList.add('w');
System.out.println(myList);

然而,这运行没有错误或异常。这怎么合法?

如果您将其声明为 List<Long>,您将获得静态编译时类型检查。执行类型擦除,JVM 在运行时对这些类型一无所知。

List<Long> myList = new ArrayList<>();
myList.add("foo");

会给出编译错误 while:

public void breakGeneric(List list) {
    list.add("foo");
}
....
List<Long> myList = new ArrayList<>();
breakGeneric(myList);

将 "foo" 添加到列表中,无论类型是什么类型。大多数 IDE 会让您厌烦失去通用类型。

在新语句 new ArrayList<Long>() 中使用类型只有在您链接该语句即 new ArrayList<Long>().add("foo") 时才会产生影响。只有这样 onlynew 语句中才会导致编译问题。

这怎么合法?

因为java编译器只考虑声明的类型,在本例中是原始类型List:

List myList

可以容纳任何类型的物体。

赋值 myList = new ArrayList<Long>()myList 的声明类型没有影响。