为什么Java不抱怨通用地图转换?

时间:2012-07-10 08:52:41

标签: java generics 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。为什么Java允许在运行时进行这样的转换?

Q2。如果使用bean,避免此错误的最佳做法是什么?

4 个答案:

答案 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的线索。