聊一聊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的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首 ...
随机推荐
- 由strcat函数引发的C语言中数组和指针问题的思考
问题一 首先,来看一下下面这段代码: #include <stdio.h> #include <string.h> int main() { char *str = " ...
- ubuntu 终端作死体验
[参考]: https://blog.csdn.net/m0_37192554/article/details/81697791 https://blog.csdn.net/amazingren/ar ...
- Python基础:七、注释
有时候我们写的东西不一定都是给用户看的,或者不希望解释器执行(方便自己,方便他人),我们可以使用#来注释掉代码被注释的内容是不会执行的,可以方便后面的程序员来拜读你的代码. 1. 单行注释:#被注释的 ...
- C# 关于变量使用范围容易犯错的问题(TreeView数据绑定为例)
asp.net做一个treeview数据绑定 绑定子节点时查询出来的数据正确,但在进行数据绑定时一直索引溢出 然后调试 ... 调试 ... 再调试... 依然很崩溃 想到了是变量定义后面共用后的问 ...
- CS萌新的汇编学习之路(其实是老师作业呵呵哒)Learning of Assembly Language
第一节课学习汇编语言,做笔记,做笔记 1.概念 首先是汇编语言这门课程的定义以及对于学习高级语言.深入理解计算机系统的作用 软硬件接口机器语言 汇编语言 高级语言 关系 机器语言和汇编语言可移植性差 ...
- mysql的基础用法,水一下
#和上一篇是一起的,上一篇就是为这个做insert <blockquote>/*思考题*/ create database spj; use spj;create table s( sno ...
- C++ 凸包生成算法
由于我的极差记忆力,我打算把这个破玩意先记下来.因为以后会有改动(Delaunay三角网生成算法),我不想把一个好的东西改坏了... 好吧-- 凸包生成算法,: 1.先在指定的宽(width)高(he ...
- Git自动化合并多个Commit
目录 git rebase逻辑 git editor的修改 处理git-rebase-todo文件 Python实现 当我们有多个commit或者从开源处拿到多个commit时,想合成一个commit ...
- [随笔][Java][修改pom仓库库为阿里云]
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- SMD 自动点料机维修
SMD 自动点料机维修 这个工具是一个好帮手,但是过完年回来发现坏了. 设置了数量不会自动停,按停止键没有反应,一定要按打印键才能停止. 这可愁死我了. 正常情况下开机设置好数量,然后开始点数,点到数 ...