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。为什么Java允许在运行时进行这样的转换?
Q2。如果使用bean,避免此错误的最佳做法是什么?
答案 0 :(得分:11)
Q1。因为在运行时,所有generic
信息都已被删除,因此两种Map
类型在运行时环境中无法区分。 generics
仅用于帮助编译器强制执行类型安全。引用Java Tutorials:
泛型是通过类型擦除实现的:泛型类型信息是 仅在编译时出现,之后它被删除 编译器。这种方法的主要优点是它提供了 通用代码与使用的遗留代码之间的完全互操作性 非参数化类型(技术上称为原始类型)。 主要缺点是参数类型信息不是 在运行时可用,并且自动生成的强制转换可能会失败 与不良行为的遗留代码进行互操作时。
Q2。不要使用原始类型的地图。如果必须的话,当你对它们进行类型转换时要非常小心。
答案 1 :(得分:0)
我认为因为类型擦除(http://docs.oracle.com/javase/tutorial/java/generics/erasure.html)而没有在runtyme中抱怨。在运行时,这个map声明没有区别。
答案 2 :(得分:0)
您在未经检查的演员表上收到编译器警告。问题是编译的字节码doesn't have any generic information,因为类型擦除问题(这是为了确保向后兼容性)所以,就JVM而言,HashMap<anything,anything>
扩展Map<anythingelse,anythingelse>
。
关于问题2:你 收到警告。不要忽视它们! ;)
答案 3 :(得分:0)
如果从Spring上下文中获取Map实例,则无法保持类型安全。 Spring BeanFactory是一个运行时容器,并没有关于实例的泛型类型params的线索。