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)
有线索吗?
该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)
伯特有正当的理由,亨宁在评论中对其进行了扩展.当引用原始类型的成员,仿制药不发挥作用可言,甚至不依赖于类型参数的泛型.
作为一个例子,这应该编译得很好......
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的泛型声明中的类型相同.
这是一个非常"陷入困境"的规则.