为什么我会丢失类型信息? [英] Why am I losing type information?

查看:83
本文介绍了为什么我会丢失类型信息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了一些有趣的地方,rawtypes和泛型。以下代码:

  static {
Map map = new HashMap();
设置< Map.Entry> set = map.entrySet(); (Map.Entry entry:set){} // fine
for(Map.Entry entry:map.entrySet()){} //编译错误
}

我得到关于类型不兼容性的编译错误,即:对象不能转换为条目。



Ideone为了方便




$为什么迭代器在 entrySet()上丢失了类型信息? b $ b

rawtypes不应该影响类型,所以 Map.Entry 突然是一个Object。或者我弄错了?

解决方案

您的示例使您看起来像您从未拥有过的类型信息。你已经写了:

  Map map = new HashMap(); 
设置< Map.Entry> set = map.entrySet(); (Map.Entry entry:set){} // fine
for(Map.Entry entry:map.entrySet()){} //编译错误

但是 map.entrySet()正在返回 Set ,而不是设置< Map.Entry> 。您已经执行了一个未检查的赋值,它会添加类型信息。



在第二个for循环中,我们不知道 Set ,所以我们不能迭代 Set< Map.Entry> ,而不进行明确的转换。



例如,比较原来的例子和我们没有使用未检查的赋值添加类型信息的例子。

  Map map = new HashMap(); 
Set set = map.entrySet(); (Map.Entry entry:set){
} //对象无法转换为Entry b $ b for(Map.Entry entry:map.entrySet()){
} //对象不能转换为Entry

在这种情况下,for循环都会产生编译错误。 / b>

这种行为在Java语言规范第4.8节中有记录:


类型的构造函数(§8.8),实例方法(§8.8,§9.4)或
非静态字段(§8.3)未从其继承的原始类型C的M
它的超类或超接口是在对应于C的
通用声明中删除它的类型。
a原始类型C的静态成员的类型与其在泛型声明中的类型相同
对应于C。



I have found something interesting to happen with Maps, rawtypes and generics. Following code:

static {
          Map map = new HashMap ();
          Set <Map.Entry> set = map.entrySet ();
          for (Map.Entry entry : set) {} // fine 
          for (Map.Entry entry : map.entrySet()) {} // compilation error
}

I am getting a compilation error about a Type incompatibility, namely: "Object cannot be cast to Entry".

Ideone for convenience

Why is the iterator over entrySet() losing the type information if there's no variable storing it again?

The rawtypes shouldn't affect the type so that Map.Entry suddenly is an Object. Or am I mistaken?

解决方案

Your example makes it look like you have type information that you never had. You have written:

Map map = new HashMap ();
Set <Map.Entry> set = map.entrySet();
for (Map.Entry entry : set) {} // fine 
for (Map.Entry entry : map.entrySet()) {} // compilation error

But map.entrySet() is returning Set, not Set <Map.Entry>. You've performed an unchecked assignment which "adds" type information.

In the second for loop, we don't know what's inside the Set, so we can't iterate over Set <Map.Entry> without an explicit cast.

For example, compare the original example to this one where we don't "add" type information with the unchecked assignment.

Map map = new HashMap();
Set set = map.entrySet();
for (Map.Entry entry : set) {
} // Object cannot be cast to Entry
for (Map.Entry entry : map.entrySet()) {
} // Object cannot be cast to Entry

In this case, both for loops produce a compilation error.

This behaviour is documented in the Java Language Specification, section 4.8:

The type of a constructor (§8.8), instance method (§8.8, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

这篇关于为什么我会丢失类型信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆