Hashmap和EnumMap的不同泛型类型擦除行为

时间:2014-04-05 17:52:12

标签: java generics map enums type-erasure

我注意到“泛型行为”中HashMapEnumMap之间存在惊讶(对我而言)。

这是什么意思?

请考虑以下两个代码段:

摘录1

enum Types { A, B, C } 
enum Wrong { A } 
public class Test { 
    public static void main(String... args) { 
        EnumMap<Types, Integer> m = new EnumMap<Types, Integer>(Types.class); 
        EnumMap m1 = m; 
        m1.put(Wrong.A, 1); 
    } 
}

出:

  

线程“main”中的异常java.lang.ClassCastException:class Wrong   !=类类型

摘录2

enum Types { A, B, C } 
enum Wrong { A } 

public class Test { 
    public static void main(String... args) { 
        HashMap<Types, Integer> m = new HashMap<Types, Integer>(); 
        HashMap m1 = m; 
        m1.put(Wrong.A, 1);            
    } 
}  

出:

成功编译!

结论:

因此,HashMap擦除fullfils但使用EnumMap的相同代码 - 不是。为什么呢?

2 个答案:

答案 0 :(得分:0)

您的第一个示例提供了一个例外,因为它期待类Types.class的实例,但您添加了一个Wrong.A的实例,它是一个不同的类。在第一个示例中,您执行删除了泛型,但它仅接受Types.class实例的事实是此EnumMap实例的属性 1}}因此没有泛型约束。

在第二个例子中没有这样的约束。没有这样的约束,因为您删除了泛型定义的约束,因此您可以放置​​Object类型的所有内容。

答案 1 :(得分:0)

您的结论不正确:两种情况都会以同样的方式发生擦除。区别在于EnumMap对象在字段中为其键类型保留类对象的引用,并使用该类对象执行反射转换。这就是引起异常的原因,你可以从堆栈跟踪中看出来。

相反,普通地图使用未经检查的强制转换,即使对象的类型不正确(导致堆污染)也会成功。