5
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

4 回答 4

11

Q1。因为在运行时,所有generic信息都已经被剥离,所以这两种Map类型在运行时环境中是无法区分的。generics它们只是为了帮助编译器强制执行类型安全。引用Java 教程

泛型是通过类型擦除实现的:泛型类型信息仅在编译时出现,之后由编译器擦除。这种方法的主要优点是它提供了通用代码和使用非参数化类型(技术上称为原始类型)的遗留代码之间的完全互操作性。主要缺点是参数类型信息在运行时不可用,并且在与行为不良的遗留代码互操作时,自动生成的强制转换可能会失败。

Q2。不要使用原始类型的地图。如果必须的话,在对它们进行类型转换时要非常小心。

于 2012-07-10T08:56:01.667 回答
0

我认为它不会因为类型擦除(http://docs.oracle.com/javase/tutorial/java/generics/erasure.html)而在runtyme中抱怨。在运行时,map 的这个声明之间没有区别。

于 2012-07-10T08:58:02.947 回答
0

您在未经检查的演员表上收到编译器警告。问题是编译后的字节码没有任何通用信息,因为类型擦除问题(这是为了确保向后兼容性)所以,就 JVM 而言,一个HashMap<anything,anything>extends Map<anythingelse,anythingelse>

至于问题 2:您收到了警告。不要忽视他们!;)

于 2012-07-10T09:01:27.077 回答
0

如果您从 Spring 上下文中获取 Map 实例,那么您将无法维护类型安全。Spring BeanFactory 是一个运行时容器,不知道实例的泛型类型参数是什么。

于 2012-07-10T10:12:37.603 回答