泛型的深入理解和案例解析(4)---类型擦除

0. 引言

   通过前三节,我们基本上掌握了泛型的基本用法和一些特定的问题解决。但是对泛型的本质原理,还未曾了解。
   我们都知道,泛型是作用在编译阶段的,让IDE帮忙检查代码。但是,到了JVM里头和普通类,普通方法,普通接口就没什么两样了。实现这种特性的专业术语叫做“类型擦除”,即在进入 JVM 之前,与泛型相关的信息会被擦除掉。
   其实java的这种设计可以理解,本质上泛型引入就是为了避免运行时的强转类型出问题,而且必须兼容老的不带泛型的代码。

1. 代码实际验证

1.1 两个不同类型的集合

	List<String> listStr = new ArrayList<>();
    List<Integer> listInt = new ArrayList<>();
    System.out.println("list is " + listInt.getClass().getName() + ", listInt.getClass() == listStr.getClass() is" + (listInt.getClass() == listStr.getClass()));

打印结果:list is java.util.ArrayList, listInt.getClass() == listStr.getClass() is true
   可以看出即使指定了不同类型,最终两者在Jvm中依然是同一个类型对象。

1.2 泛型类的成员变量

	class tiger<T> {
        private T food;
        private void eat(T food) {
            this.food = food;
        }
    }

	tiger<String> meat = new tiger<>();
    Field[] fs = meat.getClass().getDeclaredFields();
    for ( Field f:fs) {
        System.out.println("Field name "+f.getName()+" type:"+f.getType().getName());
    }

打印结果:Field name food type:java.lang.Object

   可以看到,即使指定了String,擦除类型后还是Object。这也就能够做到兼容老的代码,因为老代码都是默认Object的。

1.3 extends限制类型擦除

	class tiger<T extends String> {
        private T food;
        private void eat(T food) {
            this.food = food;
        }
    }

	tiger<String> meat = new tiger<>();
    Field[] fs = meat.getClass().getDeclaredFields();
    for ( Field f:fs) {
        System.out.println("Field name "+f.getName()+" type:"+f.getType().getName());
    }

打印结果:Field name food type:java.lang.String
   通过extends 指定了泛型是String的子类,因此类型擦除后,都是String。

2. 理解类型擦除的意义

当我们理解类型擦除,理解了最终到JVM中并没有泛型,就能够理解一些规则,而不必死记硬背。

  1. 为什么extends能够限制类型的上限,因为类型擦除后,就是它的父类。
  2. 用反射,可以在List集合中,添加String,因为类型擦除后,都是Object。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值