Java基础之类型擦除

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

public class MyT<T> {
    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());
        }
    }
}

以上方法返回结果为

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

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

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

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

public class MyT<T extends String> {
    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());
        }
    }
}

执行结果如下

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


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

public class Demo {
    public static void main(String[] args) {
        MyT<String> stringMyT = new MyT<String>();
        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);
    }
}

 运行结果如下

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

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

String info = stringMyT.info;

总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zmbwcx2003

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值