Java基础之类型擦除

03-10 1115阅读

首先我们来看一个简单案例,这是一个简单的泛型类,我们通过反射查看T是什么类型

public class MyT {
    private T info;
    public T getInfo() {
        return info;
    }
    public void setInfo(T info) {
        this.info = info;
    }
}
public class Demo {
    public static void main(String[] args) {
        Method[] methods = MyT.class.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()+"返回的类型为:"+method.getReturnType().getName());
        }
    }
}

以上方法返回结果为Java基础之类型擦除

由此我们可以看到,getInfo方法在没有指定泛型类型的时候返回类型为Object类型,如果我们呢加上返回类型结果是否会不一样呢?

public class Demo {
    public static void main(String[] args) {
        MyT stringMyT = new MyT();
        Method[] methods = stringMyT.getClass().getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()+"返回的类型为:"+method.getReturnType().getName());
        }
    }
}

Java基础之类型擦除

可以看到,即使指定了泛型类型,在获取返回类型时泛型类型依然是Object。

接下来我们修改一下MyT类,将泛型添加限定指定T继承自String

public class MyT {
    private T info;
    public T getInfo() {
        return info;
    }
    public void setInfo(T info) {
        this.info = info;
    }
}
public class Demo {
    public static void main(String[] args) {
        Method[] methods = MyT.class.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()+"返回的类型为:"+method.getReturnType().getName());
        }
    }
}

执行结果如下

Java基础之类型擦除

由此我们可以看到,T被替换成String类型,在存在多个限定符时,T会转化成第一个限定符类型


现在将限定符去掉,接着进行测试

public class Demo {
    public static void main(String[] args) {
        MyT stringMyT = new MyT();
        stringMyT.setInfo("hello");
        Method[] methods = stringMyT.getClass().getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName()+"返回的类型为:"+method.getReturnType().getName());
        }
        String info = stringMyT.getInfo();
        System.out.println(info);
    }
}

 运行结果如下

Java基础之类型擦除

这里存在一个问题,首先是我们可以确定的是,getInfo()返回类型在运行时确定为Object类型,但是在stringMyT.getInfo()时,我们并没有对返回结果进行强转但是却可以被String类型的变量接收。实际上在编译时,编译器会自动进行强转

Java基础之类型擦除

这是编译后的class文件,可以看到编译后的文件确实自动进行了强转,即使将MyT类中的info属性使用public修饰在调用时用String变量接收也是可以的。

String info = stringMyT.info;

总结

因为泛型其实只是在编译器中实现的而虚拟机并不认识泛型类项,所以要在虚拟机中将泛型类型进行擦除。也就是说,在编译阶段使用泛型,运行阶段取消泛型,即擦除。 擦除是将泛型类型以其父类代替,如String 变成了Object等。其实在使用的时候还是进行带强制类型的转化,只不过这是比较安全的转换,因为在编译阶段已经确保了数据的一致性。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]