Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Java complain about generic map casting?

Object stringMap = new HashMap<String, String>(){{ put("1", "a"); }};
Map<Integer, String> integerMap = (Map<Integer, String>)stringMap; // Why doesn't Java throw an exception at run-time?

// I know this is not a problem if stringMap is declared as Map<String, String>.
// However, the actual code above was using Spring Bean.
// Map<Integer, String> integerMap = (Map<Integer, String>)context.getBean("map");

System.out.println(integerMap.get(1)); // prints null
System.out.println(integerMap.get("1")); // prints a

Q1. Why Java allows such casting at run-time?

Q2. If using bean, what is the best practice to avoid this error?

like image 749
Sicong Avatar asked Jul 10 '12 08:07

Sicong


1 Answers

Q1. Because at run-time, all generic info is already stripped away, so the two Map types are indistinguishable for the run-time environment. The generics are only there to help the compiler enforce type safety. To quote the Java Tutorials:

Generics are implemented by type erasure: generic type information is present only at compile time, after which it is erased by the compiler. The main advantage of this approach is that it provides total interoperability between generic code and legacy code that uses non-parameterized types (which are technically known as raw types). The main disadvantages are that parameter type information is not available at run time, and that automatically generated casts may fail when interoperating with ill-behaved legacy code.

Q2. Don't use raw-typed Maps. If you have to, be really really careful when you typecast them.

like image 150
Keppil Avatar answered Oct 03 '22 09:10

Keppil