头次写博客,想说的东西不难,关于泛型的疑问,是前一阵在学习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、原始类型的概念,在下一篇博客中提及!

作者:贾博岩
链接:https://www.jianshu.com/p/1f608fd05e20
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

关于Java泛型"擦除"的一点思考的更多相关文章

  1. Java泛型擦除

    Java泛型擦除: 什么是泛型擦除? 首先了解一下什么是泛型?我个人的理解:因为集合中能够存储随意类型的对象.可是集合中最先存储的对象类型一旦确定后,就不能在存储其它类型的对象了,否则,编译时不会报错 ...

  2. 关于Java泛型实现原理的思考与一般用法示例总结

    面向对象的一个重要目标是对代码重用的支持.支持这个目标的一个重要机制就是泛型机制.在1.5版本之前,java并没有直接支持泛型实现,泛型编程的实现时通过使用继承的一些基本概念来完成的. 这种方式的局限 ...

  3. JAVA泛型-擦除

    package com.xt.thinks15_7; import java.util.Arrays; class EraseObject1<A> { } class EraseObjec ...

  4. [转] Java 的泛型擦除和运行时泛型信息获取

    原文链接 https://my.oschina.net/lifany/blog/875769 前言 现在很多程序员都会在简历中写上精通 Java.但究竟怎样才算是精通 Java 呢?我觉得不仅要熟练掌 ...

  5. Java泛型的历史

    为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...

  6. Java 泛型 Java使用泛型的意义

    Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性 ...

  7. java 泛型基础问题汇总

    泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引 ...

  8. Java泛型读书笔记 (二)

    关于Java泛型擦除后,继承一个泛型类带来的问题 有如下泛型类Pair: public class Pair<T> { private T second; private T first; ...

  9. 重学Java泛型

    一丶从字节码层面看范型擦除 public class Type1<T> { private T t; } 使用jclasslib插件查看其字节码: 可以看到 t属性的类型是List< ...

随机推荐

  1. Linux下MySQL备份以及crontab定时备份

    1. 备份某个数据库 ################################################################## # 备份某个数据库 ############ ...

  2. 为macbook双系统的windows装驱动

    网上有很多装双系统教程,这里就不再累赘,但是自己发现装完后驱动怎么装并没有交代清楚. 研究后发现,在作为驱动盘的U盘里,BootCamp文件夹下有个setup.exe 运行此程序便进行驱动的安装.

  3. 43个优秀的Swift开源项目推荐

    "轮子" 工具类 项目 开发者 备注 SwiftyJSON tangplin, lingoer GitHub 上最为开发者认可的 JSON 解析类 Dollar.swift Ank ...

  4. ZeroC Ice IceBox使用

    IceBox介绍 IceBox就像一个Tomcat,我们只要写N个Ice服务代码,用一个装配文件定义需要加载的服务列表.服务器的启动参数.启动次序等必要信息,然后启动IceBox,我们的应用系统就能够 ...

  5. 实现去哪儿来回机票选择的view

    最近有个控件是实现和去哪儿和阿里旅行的app的选择日历效果,反编译没有效果的情况下我自己实现了个,大致的原理是: 上面是产品需要实现的效果,我看了下不就是一个ListView+gridView就能实现 ...

  6. 多线程编程 NSOperation

     前言 1.NSThread的使用,虽然也可以实现多线程编程,但是需要我们去管理线程的生命周期,还要考虑线程同步.加锁问题,造成一些性能上的开销.我们也可以配合使用NSOperation和NSOper ...

  7. 通过jQuery源码学习javascript(三)

    承接上两篇继续写下去.我尽量把我明白的地方给大家说清楚.有些大家的提问我也有点搞不明白,如果有人能解答,再好不过了 疑问  第一篇中有位博友提出了以下的问题,我也不太明白,如果有明白的,能否告知一.二 ...

  8. Django Channels 入门指南

    http://www.oschina.NET/translate/in_deep_with_django_channels_the_future_of_real_time_apps_in_django ...

  9. Interesting卡常数

    C++ Interesting卡常数 作为一名OIer,在Noip中卡(kǎ 我就爱读kǎ)常数可以说是必备技巧.在此总结一下我所知卡常数的神奇手法: IO优化 fread 和 fwrite ,如果还 ...

  10. JAVA库函数总结【持续更新】

    生成随机数: Math.random()是令系统随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值. Random rand = newRandom(); rand.nextInt( ...