关于Java泛型"擦除"的一点思考

头次写博客,想说的东西不难,关于泛型的疑问,是前一阵在学习jackson中遇到的。

下面就把我所想到的、遇到的,分享出来。

泛型是JDK1.5后的一个特性,是一个参数类型的应用,可以将这个参数声明在类、接口、方法中,就像我们方法中定义的局部变量一样;在工作中,我们常在List,Map,Set等集合对象中使用,或者我们自己声明的类中使用。

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

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

直到学习了jackson后,我发现java泛型的“擦除”并不能一概而论;至少通过TypeReference接口,是可以获取到对象中的泛型;

一开始学习jackson,相关的api操作还不是很熟悉,json并没有转换成StudentEntity对象,而是变成了LinkedHashMap;研究后,发现可以使用TypeReference对象,来实现参数化类型的json转换;

有些疑问?按照之前所说,由于泛型“擦除”的原因,泛型在编译后的class文件中就不存在了,只会保留原始类型(Type中的概念),那么TypeReference又是如何实现,获取到了具体的泛型类型呢!

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

通过debug,发现确实获取到了new TypeReference<Map<String,StudentEntity>>中的泛型,至此我决定自己写个父类、子类,看看效果如何?

再次通过debug发现,并没有得到具体的泛型,而是获取到了ParameterizedTypeImpl对象(Type中的概念);此时,对于泛型更加疑惑了,感觉心中有千万只草泥马在奔腾!

于是,又回过头来看了下之前的代码 new TypeReference<Map<String,StudentEntity>>(){},发现此段代码其实是一个匿名的内部类,而编译器在编译的时候,会将此匿名内部类单独生成一个class文件,命名规则如下:主类+$+(1,2,3....)

通过反编译后,真相一目了然!

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

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

上文中,提到的Type、原始类型的概念,在下一篇博客中提及!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏章鱼的慢慢技术路

牛客网_Go语言相关练习_判断&选择题(4)

错误指的是可能出现问题的地方出现了问题,比如打开一个文件时失败,这种情况在人们的意料之中;而异常指的是不应该出现问题的地方出现了问题,比如引用了空指针,这种情况...

1212
来自专栏前端黑板报

(转)ES6新特性概览

ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony(和谐之意,显然没有跟上我国的步伐,我们已经进入中国梦版本...

2145
来自专栏飞雪无情的博客

从Java到Golang快速入门

Golang从09年发布,中间经历了多个版本的演进,已经渐渐趋于成熟,并且出现了很多优秀的开源项目,比如我们熟知的docker,etcd,kubernetes等...

1133
来自专栏desperate633

HashMap 与 HashTable的对比

而负载因子表示一个散列表的空间的使用程度,有这样一个公式:initailCapacity*loadFactor=HashMap的容量。

872
来自专栏海天一树

图的广度优先搜索

广度优先搜索算法是最简便的图的搜索算法之一,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索...

1292
来自专栏代码世界

Python之面向对象四

面向对象进阶 一、关于面向对象的两个内置函数 isinstance   判断类与对象的关系    isinstance(obj,cls)检查obj是否是类 cl...

38913
来自专栏Python中文社区

Python源码剖析之整数对象

專 欄 ❈ 松直,Python中文社区专栏作者 专栏地址: http://www.zhihu.com/people/songzhili?utm_source...

2668
来自专栏Coding迪斯尼

自制Monkey语言编译器:解释执行哈希表对象

我们在上节完成了对哈希表对象的解析,这一节我们给编译器添加执行哈希表对象的功能,完成本节代码后,编译器能执行以下代码:

882
来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版7.7节 set对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

1001
来自专栏佳爷的后花媛

java学习要点

作为一个程序员,在找工作的过程中,都会遇到笔试,而很多笔试里面都包括java,尤其是作为一个Android开发工程师,java是必备技能之一.所以为了笔试过程中...

3485

扫码关注云+社区

领取腾讯云代金券