最近在看深入理解JVM,随手写了一点代码,有个问题不太理解。
代码如下:
public static void main(String[] args) throws Exception {
HashMap<Integer, String> map = new HashMap<Integer, String>();
Method put = HashMap.class.getMethod("put", Object.class, Object.class);
put.invoke(map, 1, new Object());
System.out.println(map);
String val = map.get(1);
System.out.println(val);
}
执行结果(编译和执行版本都是1.6):
{1=java.lang.Object@2e6e1408}
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
at T002.main(T002.java:12)
报错是在String val = map.get(1);这一行。
我不解的是:
通过反射,Integer-Object键值对竟然正确地放进了Integer-String的HashMap中!
Java泛型实现原理:类型擦出
Java的泛型是伪泛型。在编译期间,所有的泛型信息都会被擦除掉。正确理解泛型概念的首要前提是理解类型擦出(type erasure)。
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
如在代码中定义的`List<object>`和`List<String>`等类型,在编译后都会编程`List`。`JVM`看到的只是`List`,而由泛型附加的类型信息对`JVM`来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。类型擦除也是Java的泛型实现方法与`C++`模版机制实现方式(后面介绍)之间的重要区别。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。