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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With