聊一聊Java泛型的擦除
最近看了《thinking in java》的第十五章泛型,感觉有些东西需要记录下来。
泛型是Java SE5才被引入的概念,现在我的工作中泛型主要使用在集合,这样可以知道set()和get()的类型(类型检查是在编译阶段,可以使用反射绕过编译),而不必再进行额外的转型操作。
今天,我们主要是来聊一聊Java泛型的擦除。
或许,你对Java泛型的擦除的概念不是很理解,下面我们来看一个例子:

很多人会认为ArrayList<String>和ArrayList<Integer>是不同的类型,但是这段程序打印的结果是true。
下面我们再来看一个例子:

这种代码在Java中是不能编译通过的,即使我传的是baby这个类的对象。但是这种代码在C++中不仅能编译通过还能执行。
这种在泛型代码内部获取不到有关泛型参数类型的一种泛型实现并不是Java的语言特性,而是Java泛型实现的一种折中。
Java的泛型是使用擦除实现的。这也就意味着当你在使用泛型的时候,任何具体的类型信息都被擦除了,你唯一知道的是你在使用一个对象。就如同上例的ArrayList<String>和ArrayList<Integer>在运行是相同的类型,它们都被擦出成它们的原生类型,List。
如果,泛型在Java 1.0中就已经是其中一部分,那么这个特性很可能就不会有擦除来实现,将会使用具体化,使类型参数保持一致,因此就可以在类型参数上执行基于类型语言的操作和反射操作。
同样,擦除的代价也是巨大的。泛型不能用于显式的引用运行时类型的操作之中,例如转型,instanceof和new。
即使,擦除在方法体内移除了有关实际类型的信息,编译器仍能够确保在方法或者类中使用的类型的内部一致性。以为擦除在方法体内移除了类型信息,所以运行时的问题的就是边界:对象进入和离开的方法的地点。这些就是编译器在编译期执行类型检查并插入转型代码的地点。下面的例子很好的说明了这点。

下面是用Javap -c Test反编译这个类看到的内容

set()和get()方法将直接存储和产生值,转型是在调用get()的时候接受检查的。
下面我们用上泛型再看看,

反编译的内容如下:

所产生的字节码相同,对进入set()的类型检查是不需要的,因为这由编辑器执行。而对从get()返回的值仍需进行转型。
所以在泛型中的所有动作都发生在边界处。
聊一聊Java泛型的擦除的更多相关文章
- java泛型-类型擦除
详细内容:参考java编程思想P373,p650. Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就 ...
- 【转】聊一聊-JAVA 泛型中的通配符 T,E,K,V,?
原文:https://juejin.im/post/5d5789d26fb9a06ad0056bd9 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型 ...
- 关于Java泛型"擦除"的一点思考
头次写博客,想说的东西不难,关于泛型的疑问,是前一阵在学习jackson中遇到的. 下面就把我所想到的.遇到的,分享出来. 泛型是JDK1.5后的一个特性,是一个参数类型的应用,可以将这个参数声明在类 ...
- 【Java心得总结三】Java泛型上——初识泛型
一.函数参数与泛型比较 泛型(generics),从字面的意思理解就是泛化的类型,即参数化类型.泛型的作用是什么,这里与函数参数做一个比较: 无参数的函数: public int[] newIntAr ...
- 【Java心得总结四】Java泛型下——万恶的擦除
一.万恶的擦除 我在自己总结的[Java心得总结三]Java泛型上——初识泛型这篇博文中提到了Java中对泛型擦除的问题,考虑下面代码: import java.util.*; public clas ...
- Java泛型-内部原理: 类型擦除以及类型擦除带来的问题
一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...
- Java泛型-类型擦除
一.概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变 ...
- Java泛型:类型擦除
类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...
- java泛型 8 泛型的内部原理:类型擦除以及类型擦除带来的问题
参考:java核心技术 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首 ...
随机推荐
- load data local to table
步骤: 1.使用show语句查找服务器上当前存在的数据库: 2.如果数据库存在,尝试访问它,之后创建表(我这里是之前创建的,所以就直接show tables) 3.将本地文件加载到表中,创建一个文本文 ...
- unity 常用插件 2
Advanced PlayerPrefs Window 用来管理 PlayerPrefs 数据,超好用 JsonDotNet JSON 的序列化/反序列化插件.这个插件是支持 iOS, Android ...
- python 集成cython 简单测试
实际开发中我们可能需要集成c/c++ 编写的模块,我们可以通过cython 解决类似的问题 以下测试一个简单的c add 方法, 使用venv 同时构建为一个pip 包 环境准备 venv 初始化 ...
- linux的基本操作(一)
一.Linux组成 1.1:Linux各模块介绍 内核:是系统的心脏,是运行程序和管理像磁盘和打印机等硬件设备的核心程序. Shell:是系统的用户界面,提供了用户和内核进行交互操作的一种接口.它接收 ...
- Unity外包团队:U3D与UE我选哪个好?请别再问这种问题了!
原本预先决定的两家VR游戏公司采访,思熊和星为棋,并没有发现什么共性之初.结果在采访之后却意外发现,两家的经历有着非常相似的地方.他们都是来自于开发游戏所用的引擎的原开发商,比如思熊的主力来自Epic ...
- php5.5.7添加pgsql,pdo_pgsql,swoole
一:下载php源码sudo wget cn2.php.net/distributions/php-X.X.X.tar.gz 二:解压 tar xzf /php-X.X.X.tar.gz 三:进入源码e ...
- python读写文件\r\n问题
newline controls how universal newlines mode works (it only applies to text mode). It can be None, ' ...
- 《剑指offer(第二版)》面试题60——n个骰子的点数
一.题目描述 把n个骰子仍在地上,所有的骰子朝上的一面的点数之和为s,输入n,打印出s所有可能的值出现的概率. 二.题解 <剑指offer>上给出的两种方法,尤其是代码,晦涩难懂且没有注释 ...
- 理解OpenShift(5):从 Docker Volume 到 OpenShift Persistent Volume
理解OpenShift(1):网络之 Router 和 Route 理解OpenShift(2):网络之 DNS(域名服务) 理解OpenShift(3):网络之 SDN 理解OpenShift(4) ...
- (转)通过注册表修改VC6.0的字体
出处:http://www.cnblogs.com/PocketZ 在VC6.0下更改字体,我们一般通过菜单-Tools-Options-Format来更改 但在我的win7 64位系统下这一选项下的 ...