java中泛型擦除_Java 的泛型擦除

说到泛型,就不得说起“擦除”这个概念,相比于c#来说,java的泛型只存在于程序的源码中,在编译后的class文件中不存在,这个过程就是--泛型"擦除";所以,对于new ArrayList 和 new ArrayList 来说,两个对象在编译之后两者是一样的,通过反射均可以向集合中添加任意类型的对象;

编译前:

public static void main(String[] args) {

Class c1 = new ArrayList().getClass();

Class c2 = new ArrayList().getClass();

System.out.println(c1 == c2);

}

编译后:

public static void main(String[] args) {

new ArrayList();

new ArrayList();

}

可以看到,在编译后的class文件中,ArrayList所声明的泛型不存在了;由此可知,如果想在程序运行期间获取泛型,看似是一件不可能完成的事情!

Map map = new HashMap<>();

map.put(0, 0L);

map.put(1, 1L);

String a = JSON.toJSONString(map);

map = JSON.parseObject(a, new TypeReference>(){});

按照泛型擦除,泛型在编译后的class文件中就不存在了, 知会保留原始类型(Type的概念),那么TypeReference又是如何获取到具体的泛型类型的呢?

查看TypeReference的源码,发现在其构造方法中,主要使用到了getGenericSuperclass()和getActualTypeArguments()两个方法,getGenericSuperclass()返回的是此对象带“泛型”的父类,而getActualTypeArguments()返回的是此父类中实际类型参数的Type 对象数组,说白了就是TypeReference<>中的泛型;

如果非匿名内部类,通过getActualTypeArguments() 获取的仍然是Type中的概念;如果声明了匿名内部类,则在编译时会将此匿名内部类但对生成一个class文件

创建的匿名内部类new TypeReference>(){},在生成的的class文件中,编译器默认为TypeReference中的泛型Map原始类型,并不会进行擦除!类似于 我们实际创建一个类 Class TypeReference>{} ,和Class Test{}一样,在编译后Map、T依旧会存在!

由此,对于java泛型的“擦除”并不能一概而论,在运行期间,如果方法中出现带泛型的匿名内部类,那么泛型依旧会被保留下来,我们可以通过对应的方法获取到实际的泛型类型!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值