大家应该都有泛型在编译期会被擦除的概念,那么为什么我们在运行时还能读取到呢?
原因是因为编译器帮我们完成了自动类型转换,因为类型擦除的问题,泛型类型变量最后得到的都是原始类型; Java自动的帮我们进行了一个类型转换checkcast指令,更通俗的理解就是,泛型进入的地方因为类型擦除,默认转型成为了Object对象,然后在泛型离开的地方,编译器为我们自动加上了将Object转型成Target对象的指令。
其实在泛型擦除时并不会将所有的泛型类型都擦除掉,它只会擦除运行时的泛型类型,编译时类中定义的泛型类型是不会被擦除的,对应的泛型类型会被保存在Signature中。
我们如果想获取对应对象中的泛型类型只需将动态创建的对象改为匿名内部类即可获取,因为内部类实在编译时创建的,泛型类型是会保存下来的
对应API getGeneric...都是获取泛型类型的
泛型的擦除机制实际上擦除的是除结构化信息外的所有东西(结构化信息指与类结构相关的信息,而不是与程序执行流程有关的,即与类及其字段和方法的类型参数相关的元数据都会被保留下来通过反射获取到)。
Java中的编译时和运行时
在由
.java
文件生成.class
文件的过程中,由编译器对代码进行处理的过程就叫做编译时处理,比如静态常量的替换,方法的重载等等;而运行时处理是由JVM虚拟机执行.class
的过程泛型在编译时和运行时的处理:
- 在编译过程中,编译器会对泛型做优化处理。通过对比
.java
文件和.class
文件我们可以发现,我们创建的泛型会被替换成实际的类型,这是因为在编译时会进行类型检测,然后替换成实际的对象类型,这个过程被称为“类型擦除”- 在运行过程中,所有的泛型类型在进入时都会被转化成Object对象,然后在泛型离开的地方,编译器为我们自动加上了将Object转型成Target对象的指令;这个时候我们可以将动态创建的对象改为匿名内部类对象(在编译时创建)
重写:运行时处理,在JVM执行的过程中才能确定,又称为运行时多态
重载:编译时处理
注解:有运行时注解也有编译时注解
异常:有运行时异常也有编译时异常
继承:编译时处理,静态的过程,在编译后就已经确定
代理:运行时处理
网友评论