首页
学习
活动
专区
圈层
工具
发布

堆污染
EN

Stack Overflow用户
提问于 2011-08-19 08:20:16
回答 2查看 474关注 0票数 6
代码语言:javascript
复制
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文档说;

此外,当调用

方法时,会出现堆污染的情况。add方法的静态类型第二形式参数是String,但是该方法是用另一种类型的实际参数Integer调用的。但是,编译器仍然允许此方法调用。由于类型擦除,add方法(定义为List.add(int,E))的第二个形式参数的类型成为对象。因此,编译器允许此方法调用,因为在类型擦除之后,l.add方法可以添加任何类型为对象的对象,包括整数类型的

对象。

我的问题是关于我大胆的部分。我理解在第2行中,堆污染的发生是因为List引用了一个类型为List的对象。但是,当对l引用调用add方法时,不应该期望数字类型而不是字符串类型,因为l是对ArrayList的引用。或者,在ls=l之后,堆中的空间也是由List<String>构成的,用于l引用吗?在本例中,java文档在粗体部分中的内容是有意义的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-19 08:25:36

,但是当对l引用调用add方法时,它不应该期望数字类型而不是字符串类型,因为l是对ArrayList的引用。

List l被声明为非类型化列表。因此,编译器将允许您输入您喜欢的任何内容(并对其发出警告),并将其分配给不兼容的List<String>变量(并对其发出警告)。

如果您说的是List<Number> l,编译器将强制执行正确的类型(而不允许将它分配给ls)。

无论您声明或不声明哪种泛型类型,这在运行时都没有任何影响。为了保持向后兼容性,泛型是一个完整的编译时特性.

还是说,ls=l之后堆中的空间也是由List构成的呢?

如果你说

代码语言:javascript
复制
List l = new ArrayList<Integer>();
List<String> ls = l;
Object x = ls;
Collection<?> c = (Collection) x;

您有四个不同的变量(有四个不同的类型声明),但它们都指向相同的数据(堆上的相同对象)。

票数 7
EN

Stack Overflow用户

发布于 2011-08-19 08:26:02

错误在第一行。您将l声明为非类型安全列表。将第一行改为:

代码语言:javascript
复制
List<Number> l = new ArrayList<Number>();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7118784

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档