Java语法糖1 泛型与类型擦除

1 泛型与类型擦除

泛型是JDK 1.5的一项新增特性,它的本质是参数化类型(Parametersized Type) 的应用,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类,接口和方法的创建中, 分別称为泛型类、泛型接口和泛型方法。

在Java语言处于还没有出现泛型的版本时。只能通过Object 是所有类型的父类和类型强制转换两个特点的配合来实现类型泛化。例如,在哈希表的存取中,JDK 1.5之前使用HashMap的get() 方法,返回值就是个0bject。由于Java语言里面所有的类型都维承于java.lang.Object 所以Object转型成任何对象都是有可能的。但是也因为有无限的可能性。就只有程序员和运行期的虚拟机才知道这个Objet到底是个什么类型的对象。在编译期间,编译器无法检查这个Object的强制转型是否成功。如果仅仅依赖程序员去保障这项操作的正确性,许多ClassCastException的风险就会转嫁到程予运行期之中。

Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type) ,并且在相应的地方插入了强制转型代码,因此,对于运行期的Java来说Araylist<int>Aralist<String>就是同一个类。所以泛型是Java语言的一颗语法糖Java称为类型擦除,基于这种方法实现的泛型称为伪泛型。

泛型擦除前的例子

把这段Java代码编译成Class文件,然后再用字节码反编译后,將会发现泛型都不见了,又变回了Java泛型出现之前的写法,泛型类型都变回了原类型.如

通过擦除來实现泛型丧失了一些泛型思想应有的优雅

当泛型遇见重载1

不能被编译的,因为参数List<Integer>和List<String>编译之后都被擦除了。变成了一样的原生类型List<E>,擦除动作导致这两种方法的特征签名变得一模一样。初步看来,无法重载的原因已经找到了,但真的就如此吗? 只能说,泛型擦除成相同的原生类型只是无法重载的部分原因

当泛型遇见置载2

由于Java泛型的引入,各种场景(虚拟机解析,反射等> 下的方法调用都可能对原有基础产生影响,如在泛型类中如何获取传入的参数化类型等。因此,JCP组织对虚拟机规范做出了相应的修改,引人了诺如Signature,LocalVariableTypeTable 等新的属性用于解决伴随泛型而来的参数类型的识别问题,Signature 是其中最重要的一项属性,它的作用就是存储一个方法在字节码层面的特征签名,这个属性中保存的参数类型并不是原生类型,而是包括了参数化类型的信息。修改后的虚拟机规范裂水所有能识别49.0以上版本的Class 文件的虚拟机都要能正确地识别Signature参数.

从Signature属性的出现我们还可以得出结论,所谓的擦除,仅仅是对方法的Code属性中的宇节码进行擦除,实际上元数据还是保留了泛型信息,这也是我们能通过反射取得参数化类型的根本依据。

自动装箱: 拆箱与遍历循环

自动装箱: 拆箱与遍历循环编译后

遍历循环则把代码还原成了迭代器的实现,这也是为何遍历循环需要被遍历的类实现Iterable接口的原因。最后再看看变长参数,它在调用的时候变成了一个数组类型的参数,在变长参数出现之前,程序员就是使用数组来完成类似功能的。

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Vamei实验室

Python标准库01 正则表达式 (re包)

我将从正则表达式开始讲Python的标准库。正则表达式是文字处理中常用的工具,而且不需要额外的系统知识或经验。我们会把系统相关的包放在后面讲解。 正则表达式(r...

2859
来自专栏Java帮帮-微信公众号-技术文章全总结

shell编程基础入门

shell编程基础入门 文章最后有下载shell学习指南电子书链接。 1.shell格式:例 shell脚本开发习惯 1.指定解释器 #!/bi...

3404
来自专栏阮一峰的网络日志

在PHP语言中使用JSON

我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识。

1233
来自专栏决胜机器学习

《Redis设计与实现》读书笔记(三十三) ——Redis排序命令sort的实现

《Redis设计与实现》读书笔记(三十三) ——Redis排序命令sort的实现 (原创内容,转载请注明来源,谢谢) 一、基本功能 redis的sort命令,可...

3895
来自专栏DT乱“码”

java 异常处理

在java的异常处理机制中,有两种异常处理方式,一种是throw往外抛异常,一种是try...catch...捕获异常处理异常。那么一般情况下,什么时候用thr...

2098
来自专栏Python爬虫与数据挖掘

Python正则表达式初识(八)

继续分享Python正则表达式的基础知识,今天给大家分享的特殊字符是“\w”和“\W”,具体的教程如下。

1205
来自专栏微信公众号:Java团长

Java动态代理原理及解析

代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类...

944
来自专栏liulun

Nim教程【十五】【完结】

模版 模版是Nim语言中的抽象语法树,它是一种简单的替换机制,在编译期被处理 这个特性使Nim语言可以和C语言很好的运行在一起 像调用一个方法一样调用一个模版 ...

2278
来自专栏北京马哥教育

Python 面试问答 Top 25

Python 是一种解释型,交互式,面向对象的高级编程语言。和别的一些使用标点符号的语言不同,Python使用了大量的英语单词作为关键字,因而具有很好的可读性...

3526
来自专栏老马说编程

计算机程序的思维逻辑 (12) - 函数调用的基本原理

栈 上节我们介绍了函数的基本概念,在最后我们提到了一个系统异常java.lang.StackOverflowError,栈溢出错误,要理解这个错误,我们需要理...

20910

扫码关注云+社区

领取腾讯云代金券