头次写博客,想说的东西不难,关于泛型的疑问,是前一阵在学习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. XMPP系列(五)---文件传输

    xmpp中发送文件和接收文件的处理有些不太一样,接收文件处理比较简单,发送稍微复杂一些. 首先需要在XMPPFramework.h中添加文件传输类 //文件传输 //接收文件 #import &quo ...

  2. MarioTCP:一个单机可日30亿的百万并发长连接服务器

    原文:http://blog.csdn.net/everlastinging/article/details/10894493 注:如果用此服务器做变长data的传输,请在业务处理函数中为input ...

  3. Linux内核中断和异常分析(下)

    这节,我们继续上,中(以前的日志有)篇目进行分析,结合一个真实的驱动案例来描述linux内核中驱动的中断机制,首先我们先了解一下linux内核中提供的中断接口. 这个接口我们需要包含一个头文件:#in ...

  4. HDFS的java api操作

    hdfs在生产应用中主要是针对客户端的开发,从hdfs提供的api中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS上的文件. 搭建开发环境 方式一(windows环境下 ...

  5. linux 下使用 tc 模拟网络延迟和丢包

    1 模拟延迟传输简介 netem 与 tc: netem 是 Linux 2.6 及以上内核版本提供的一个网络模拟功能模块.该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,诸如低带 ...

  6. AngularJs 指令directive之require

    controller的用法分为两种情形,一种是require自定义的controller,由于自定义controller中的属性方法都由自己编 写,使用起来比较简单:另一种方法则是require An ...

  7. js常用 弹出确认 取消对话框

    <!DOCTYPE html><html><head> <title></title> <meta charset='utf-8'&g ...

  8. Tracert(跟踪路由)是路由跟踪实用程序,用于确定 IP 数据包访问目标所采取的路径。

    Tracert(跟踪路由)是路由跟踪实用程序,用于确定 IP 数据包访问目标所采取的路径.   Tracert 命令用 IP 生存时间 (TTL) 字段和 ICMP 错误消息来确定从一个主机到网络上其 ...

  9. Day15 Javascipt内容补充

    JavaScript函数: 函数: function 函数名(a,b,c){ 执行代码 } 1,如何去找到标签 Dom直接选择器: 1,找到标签 #获取单个元素 document.getElement ...

  10. cannot import name '_imaging' 与No module named PIL解决方法

    今天学习廖雪峰的python 第三方模块pillow一章. 直接使用from PIL import Image 会报"No module named PIL",显然这是没有安装pi ...