简体   繁体   English

java.util.Map入口集的问题

[英]Problem with entry set of java.util.Map

I'm having a strange problem with the following code works. 我遇到以下代码的奇怪问题。

Map<String, Object> map = new HashMap<String, Object>();

for(Entry<String, Object> entry : map.entrySet()) {
   // 
}

while the code below does not compile. 而下面的代码不编译。

Map map = new HashMap();

for(Entry entry : map.entrySet()) {  // compile error here
   // 
}

Any clues? 有线索吗?

The entrySet method signature is Set<Map.Entry<K, V>> entrySet() so you can only refer to Map.Entry if you've declared the generic types in the declaration like you did in the first example. entrySet方法签名是Set<Map.Entry<K, V>> entrySet()因此如果您在声明中声明了泛型类型,就像在第一个示例中所做的那样,您只能引用Map.Entry In the second you're using raw types, so it's essentially Set<Object> entrySet() and you'd need a cast for it to work, eg 在第二个你正在使用原始类型,所以它基本上是Set<Object> entrySet() ,你需要一个强制转换才能工作,例如

final Map map = new HashMap();

for(final Entry entry : (Set<Entry>)map.entrySet()) {
   // 
}

Burt has the right reason and Henning expands on it in the comments. 伯特有正当的理由,亨宁在评论中对其进行了扩展。 When referencing a member of a raw type, generics don't come into play at all , even generics that don't rely on the type parameter . 当引用原始类型的成员,仿制药不来发挥作用的一切甚至不依赖于类型参数的泛型

As an example, this should compile just fine... 作为一个例子,这应该编译得很好......

public class DataHolder<T> {
    public List<T> ts;
    public List<String> strings = new ArrayList<String>();
}

//...
DataHolder holder = new DataHolder();
holder.strings.add(Integer.valueOf(42));

...even though T doesn't need to be mapped to a concrete type to know what the type of strings should be. ...即使T不需要映射到具体类型来知道strings的类型应该是什么。

This is true for generic member methods as well, which is what you are running into. 对于通用成员方法也是如此,这正是您遇到的问题。 entrySet returns the raw type Set , not Set<Entry> , even though the type parameters would not need to be known to return a Set<Entry> . entrySet返回原始类型Set ,而不是Set<Entry> ,即使不需要返回Set<Entry>也不需要知道类型参数。 The behaviour is documented in the Java Language Specification, section 4.8 : 该行为记录在Java语言规范的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. 未从其超类或超接口继承的原始类型C的构造函数(第8.8节), 实例方法 (第8.8节,第9.4节)或非静态字段(第8.3节)M的类型是其类型的擦除在对应于C的泛型声明中。原始类型C的静态成员的类型与对应于C的泛型声明中的类型相同。

It's a very "gotcha" rule. 这是一个非常“陷入困境”的规则。

See also 也可以看看

Java Class Generics and Method Generics conflicts Java类泛型和方法泛型冲突

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM