什么是类型擦除?
类型擦除指的是一些信息仅存在于源码阶段,编译之后就不存在。类型擦除在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
        }
    }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐