【问题标题】:Why doesn't Java complain about generic map casting?为什么 Java 不抱怨泛型映射转换?
【发布时间】:2012-07-09 17:18:47
【问题描述】:
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

第一季度。为什么 Java 允许在运行时进行这种类型转换?

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

【问题讨论】:

    标签: java generics map casting


    【解决方案1】:

    第一季度。因为在运行时,所有generic 信息已经被剥离,所以这两种Map 类型对于运行时环境是无法区分的。 generics 仅用于帮助编译器强制执行类型安全。引用Java Tutorials

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        您在未经检查的强制转换时收到编译器警告。问题是编译的字节码 doesn't have any generic information 因为类型擦除问题(这是为了确保向后兼容性)所以,就 JVM 而言,HashMap&lt;anything,anything&gt; 扩展了 Map&lt;anythingelse,anythingelse&gt;

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-27
            • 2013-09-16
            • 2019-07-09
            • 2011-12-28
            • 2015-06-09
            • 2020-08-12
            相关资源
            最近更新 更多