Java堆污染

托马斯:
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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章