Pergunta

I noticed surprising(for me) difference between HashMap and EnumMap in 'generics behaviour'.

What does it mean?

Consider the following two code snippets:

snippet 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); 
    } 
}

out:

Exception in thread "main" java.lang.ClassCastException: class Wrong != class Types

snippet 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);            
    } 
}  

out:

successful compilation!

Conclusion:

Therefore for HashMap erasure fullfils but for same code with EnumMap - not. Why?

Foi útil?

Solução

Your conclusion is incorrect: Erasure occurs in both cases, and in the same way. The difference is that the EnumMap object keeps a reference the class object for its key type in a field, and uses that class object to perform a reflective cast. That is what is causing the exception, as you can tell from the stacktrace.

In contrast, an ordinary map uses an unchecked cast, which succeeds even if the object is of an incorrect type (giving rise to heap pollution).

Outras dicas

Your first example gives an exception, because it is expecting instances of class Types.class, but you add one instance of Wrong.A, which is of a different class. In the first example you do get rid of the generics, but the fact that it accepts only instances of Types.class is a property of this instance of the EnumMap and thus no generics constraint.

In the second example there is no such constraint. There is no such constraint, because you remove the generics-defined constraints there, so you can put everything of type Object.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top