List l = new ArrayList<Number>();
List<String> ls = l; // unchecked warning
l.add(0, new Integer(42)); // another unchecked warning
String s = ls.get(0); // ClassCastException is thrown
Java文档说;
此外,调用l.add方法时会发生堆污染情况。add方法的静态类型第二形式参数是String,但是此方法是使用不同类型的实际参数Integer调用的。但是,编译器仍然允许此方法调用。由于类型擦除,add方法的第二个形式参数(定义为List.add(int,E))的类型成为Object。因此,编译器允许此方法调用,因为在擦除类型之后,l.add方法可以添加任何Object类型的对象,包括Integer类型的对象
我的问题是关于我大胆的部分。我知道在第2行中会发生堆污染,这是因为List of引用了List类型的对象。但是当在l引用上调用add方法时,它不应期望Number类型而不是String,因为l是对ArrayList的引用。还是在ls = l之后,堆中的空间List<String>
也由l引用组成?在这种情况下,java文档在以粗体显示的部分中说的是有意义的
但是当在l引用上调用add方法时,它不应期望Number类型而不是String,因为l是对ArrayList的引用。
List l
只是声明为无类型的列表。因此,编译器将允许您放入所需的任何内容(并对其进行警告),然后将其分配给不兼容的List<String>
变量(并对其进行警告)。
如果您说List<Number> l
,则编译器将强制使用适当的类型(并且不允许您将其分配给ls
)。
无论您声明或不声明什么泛型类型,这在运行时都无效。为了保持向后兼容性,泛型是一个完整的仅编译时功能。
还是在ls = l之后,堆中的空间也由List组成,以供l参考?
如果你说
List l = new ArrayList<Integer>();
List<String> ls = l;
Object x = ls;
Collection<?> c = (Collection) x;
您有四个不同的变量(具有四个不同的类型声明),但是它们都指向同一数据(堆上的同一对象)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句