java.util.Map入口集的问题

fas*_*ava 8 java generics collections iterator

我遇到以下代码的奇怪问题.

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

for(Entry<String, Object> entry : map.entrySet()) {
   // 
}
Run Code Online (Sandbox Code Playgroud)

而下面的代码不编译.

Map map = new HashMap();

for(Entry entry : map.entrySet()) {  // compile error here
   // 
}
Run Code Online (Sandbox Code Playgroud)

有线索吗?

Bur*_*ith 8

entrySet方法的签名是Set<Map.Entry<K, V>> entrySet()这样,你只能引用Map.Entry就像你在第一个例子,如果你声明的泛型类型的声明.在第二个你正在使用原始类型,所以它本质上是Set<Object> entrySet()你需要一个演员才能工作,例如

final Map map = new HashMap();

for(final Entry entry : (Set<Entry>)map.entrySet()) {
   // 
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 5

伯特有正当的理由,亨宁在评论中对其进行了扩展.当引用原始类型的成员,仿制药不发挥作用可言,甚至不依赖于类型参数的泛型.

作为一个例子,这应该编译得很好......

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));
Run Code Online (Sandbox Code Playgroud)

...即使T不需要映射到具体类型以了解strings应该是什么类型.

对于通用成员方法也是如此,这正是您遇到的问题. entrySet返回原始类型Set,而不是Set<Entry>,即使返回a不需要知道类型参数Set<Entry>.该行为记录在Java语言规范的4.8节中:

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

这是一个非常"陷入困境"的规则.

也可以看看

Java类泛型和方法泛型冲突