什么是类型擦除?
类型擦除指的是一些信息仅存在于源码阶段,编译之后就不存在。类型擦除在Java中有泛型,自动拆装箱。
泛型信息仅存在于代码编译阶段,进入JVM之前,与反向相关信息会被擦除。即泛型类和普通类在Java虚拟机内没有任何区别。
通过代码看编译之后类的类型类:
package CODE.泛型;
class Me<T>
{
private T data;
}
public class Erase
{
public static void main(String[] args)
{
Me<String> m1=new Me<>();
Me<Integer> m2=new Me<>();
//打印两个在jvm中的Class,获得类型的类型类
System.out.println(m1.getClass()); //class CODE.泛型.Me
System.out.println(m2.getClass()); //class CODE.泛型.Me
}
}
通过结果可以发现,泛型类在编译之后类型一样,也就是发生了类型擦除。
泛型类进入JVM之前,会进行类型擦除,之前泛型类的类型参数若没有指定上限,会被擦除为Object类。如果指定上限,则类型参数会被替换为相应类型上限。
代码如下:
import java.lang.reflect.Field;
class MyErase<T,E extends Number> // E 只能是Number及其子类
{
private T data1;
private E data2;
public MyErase(T data1,E data2)
{
this.data1=data1;
this.data2=data2;
}
}
//类型擦除
public class Erase
{
public static void main(String[] args)
{
MyErase<String,Integer> m1=new MyErase<>("pick",10);
Class cl=m1.getClass();
//getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
Field[] field=cl.getDeclaredFields();
for(Field data :field)
{
//getType返回声明字段的类型
System.out.println(data.getType()); //class java.lang.Object class java.lang.Number
//由于会有类型擦除,T没有指定上限会被擦除为Object
//class java.lang.Object
//E extends Number,指定上限为Number,类型擦除后成为Number
//class java.lang.Number
}
}
}