【发布时间】:2018-10-06 16:31:14
【问题描述】:
我不明白编译器如何处理以下代码,因为它输出 Test 而我期待一个错误。
List<Integer> b = new ArrayList<Integer>();
List a = b;
a.add("test");
System.out.println(b.get(0));
我希望有人能告诉我编译器在执行代码时经过的确切步骤,以便我理解输出。我目前的理解是:
- 编译器会在编译期间检查 List 类中是否存在支持参数类型的 add 方法,该类是 add(Object e) 作为其原始类型。
- 但是,在运行时,它会尝试从实际对象 List
调用 add(Object e),该对象不包含此方法,因为实际对象不是原始类型,而是包含add(Integer e) 方法。
如果实际对象 List
【问题讨论】:
-
列表不执行类型检查。毕竟这只是一个引用数组,所以是的,它会工作,但它是不安全的!
-
a列表是原始的,这意味着它存储了Object引用。因此,您可以向其中添加任何 Java 类,因为所有内容都隐式扩展了Object。如果您尝试将String添加到b列表中,该错误就会起作用。这会在编译时失败,因为泛型会阻止这种情况发生。 -
很好的问题,你很接近。您的第 1 项是正确的,但 Java 有一个名为 type erasure 的东西,因此您的第 2 项实际上并不适用。
-
如果实际对象 List
中没有 add(Object e) 方法,那你就搞错了。这是一个 List,在运行时它是一个List<Object>,所以是一个add(Object)。编译器插入一个类型转换,这就是失败的原因。 -
泛型是编译时检查,通过
List a = b,您将关闭编译时检查。
标签: java generics collections polymorphism raw-types