聊一聊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的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首 ...
随机推荐
- antd-vue按需加载插件babel-plugin-import报错
报错.bezierEasingMixin().百度了一下是Less版本太高的原因,我都迷了,还有太新的过... 解决方法:将less版本降到3.0以下 因为我是用的npm生成的vue项目.所以cmd命 ...
- Centos7.4下安装Jumpserver 1.0.0(支持windows组件)
0)系统环境CentOS 7.4 IP: 192.168.100.10 [root@jumpserver-server ~]# cat /etc/redhat-release CentOS Linux ...
- 学习笔记CB008:词义消歧、有监督、无监督、语义角色标注、信息检索、TF-IDF、隐含语义索引模型
词义消歧,句子.篇章语义理解基础,必须解决.语言都有大量多种含义词汇.词义消歧,可通过机器学习方法解决.词义消歧有监督机器学习分类算法,判断词义所属分类.词义消歧无监督机器学习聚类算法,把词义聚成多类 ...
- golang常见错误
import import unuse package: error : imported and not used: "os" := = c := 1 // error non- ...
- Actifio如何保护和管理Oracle-带外篇
引言 本文提供CDS带外环境下相关配置,保护和恢复Oracle的所需步骤. 目的是提供Oracle数据库配置前的详细说明,Actifio环境下发现和配置Oracle数据库,执行还原和恢复,以及配置Or ...
- [随笔][Java][something]
import 只能导入包中的类,不能导入某个包.为了方便,一般不导入单独的类,而是导入包下的所有类.import java.util.*; 包java.lang中的所有类默认由编译器全部导入了,不必手 ...
- 在kerberos认证过程中Active Directory的作用
LDAP介绍 1),ladp(Lightweight Directory Access Protocol),轻量级目录访问协议,提供被称为目录服务的信息服务,特别是基于X.500(构成全球分布式的目录 ...
- 2018-2019-2 20175202实验二《Java面向对象程序设计》实验报告
2018-2019-2 20175202实验二<Java面向对象程序设计>实验报告 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初 ...
- install rust
Step 1. Trial 1 Download rustup-init.exe exec rustup-init.exe SW hangs 2. Trial 2 install rust-1.33. ...
- python selenium-webdriver 常用浏览器的操作 (十)
浏览器常用的一些方法和属性其实很简单一些方法,但是却在实际测试过程中经常使用. 浏览器中加载url 方法:get(url) 实例:driver.get("http//:www.baidu.c ...