类型擦除

学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组、无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦);(2)ArrayList<Integer>和ArrayList<String>在运行时的类型是相同的。Java中的泛型有这些问题,是它的实现机制决定的,即“类型擦除”。

  1. 类型擦除的定义:编译通过后,准备进入JVM运行时,就不再有类型参数的概念,换句话说:每定义一个泛型类型,JVM会自动提供一个对应的原生类;
public class Holder4<T> { private T a; private T b; private T c; public Holder4(T a, T b, T c) { this.a = a; this.b = b; this.c = c; } public T getA() { return a; } public T getB() { return b; } public T getC() { return c; } public void setA(T a) { this.a = a; } public void setB(T b) { this.b = b; } public void setC(T c) { this.c = c; } public static void main(String[] args) { Holder4<Automobile> holder4 = new Holder4<>(new Automobile(),new Automobile(), new Automobile()); Automobile a = holder4.getA(); //编译器帮忙转型,不需要显式转型 Automobile b = holder4.getB(); Automobile c = holder4.getC(); } } 

在Java中,每定义一个泛型类型,就会自动提供一个对应的原始类型,例如:

public class Holder4Raw {private Object a; private Object b; private Object c; public Holder4Raw(Object a, Object b, Object c) { this.a = a; this.b = b; this.c = c; } public Object getA() { return a; } public Object getB() { return b; } public Object getC() { return c; } public void setA(Object a) { this.a = a; } public void setB(Object b) { this.b = b; } public void setC(Object c) { this.c = c; } public static void main(String[] args) { Holder4Raw holder4Raw = new Holder4Raw(new Automobile(),new Automobile(), new Automobile()); Automobile a = (Automobile) holder4Raw.getA(); //显示的转型 Automobile b = (Automobile) holder4Raw.getB(); Automobile c = (Automobile) holder4Raw.getC(); } } 

  1. 为什么选择这种实现机制?
  • 在Java诞生10年后,才想实现类似于C++模板的概念,即泛型;
  • Java的类库是Java生态中非常宝贵的财富,必须保证向后兼容(即现有的代码和类文件依旧合法)和迁移兼容(泛化的代码和非泛化的代码可互相调用)基于上面这两个背景和考虑,Java设计者采取了“类型擦除”这种折中的实现方式。
  1. Java泛型依赖编译器实现,只存在于编译期,JVM中没有泛型的概念;那么,编译器做了什么工作呢?(1)set方法是编译期检查;(2)get方法的返回值进行转型,编译器插入了一个checkcast语句。

我们通过字节码进行观察,可以看出:(1)Holder4和Holder4Raw两个类的字节码完全相同;(2)在main函数的33、41和49行就是编译器插入的checkcast语句;

public class org.java.learn.generics.Holder4<T> { public org.java.learn.generics.Holder4(T, T, T); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: aload_1 6: putfield #2 // Field a:Ljava/lang/Object; 9: aload_0 10: aload_2 11: putfield #3 // Field b:Ljava/lang/Object; 14: aload_0 15: aload_3 16: putfield #4 // Field c:Ljava/lang/Object; 19: return public T getA(); Code: 0: aload_0 1: getfield #2 // Field a:Ljava/lang/Object; 4: areturn public T getB(); Code: 0: aload_0 1: getfield #3 // Field b:Ljava/lang/Object; 4: areturn public T getC(); Code: 0: aload_0 1: getfield #4 // Field c:Ljava/lang/Object; 4: areturn public void setA(T); Code: 0: aload_0 1: aload_1 2: putfield #2 // Field a:Ljava/lang/Object; 5: return public void setB(T); Code: 0: aload_0 1: aload_1 2: putfield #3 // Field b:Ljava/lang/Object; 5: return public void setC(T); Code: 0: aload_0 1: aload_1 2: putfield #4 // Field c:Ljava/lang/Object; 5: return public static void main(java.lang.String[]); Code: 0: new #5 // class org/java/learn/generics/Holder4 3: dup 4: new #6 // class org/java/learn/generics/Automobile 7: dup 8: invokespecial #7 // Method org/java/learn/generics/Automobile."<init>":()V 11: new 

Java泛型之类型擦除相关推荐

  1. Java泛型:类型擦除

    前情回顾 Java泛型:泛型类.泛型接口和泛型方法 类型擦除 代码片段一 1 2 3 4 5 6 7 Class c1 = new ArrayList<Integer>().getClas ...

  2. java 泛型和类型擦除_关于Java泛型和擦除

    java 泛型和类型擦除 "编译期间擦除泛型"是常识(好吧,类型参数和实参实际上是被擦除的). 这是由于"类型擦除"而发生的. 但这是错误的,正如许多开发人员所 ...

  3. Java泛型的类型擦除

    写在前面:最近在看泛型,研究泛型的过程中,发现了一个比较令我意外的情况,Java中的泛型基本上都是在编译器这个层次来实现的.在生成的Java字节代码中是不包含泛型中的类型信息的.使用泛型的时候加上的类 ...

  4. Java泛型与类型擦除--ImportNew

    本文由 ImportNew - 伍翀 翻译自 On Java Generics and Erasure.欢迎加入翻译小组.转载请参见文章末尾的要求. "编译器会进行泛型擦除"是一个 ...

  5. 描述java泛型引入原则_Java/泛型的类型擦除/README.md · oslo/LearningNotes - Gitee.com

    前言 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类型在编译后都会被清除掉,看下 ...

  6. java object toarray_java从toArray返回Object[]到泛型的类型擦除

    在将ArrayList等Collection转为数组时,函数的返回值并不是泛型类型的数组,而是Object[].刚好最近翻了一遍<java核心技术>,以及参考<Think in Ja ...

  7. java中的类型擦除type erasure

    文章目录 简介 举个例子 原因 解决办法 总结 java中的类型擦除type erasure 简介 泛型是java从JDK 5开始引入的新特性,泛型的引入可以让我们在代码编译的时候就强制检查传入的类型 ...

  8. Java基础篇:泛型与类型擦除

    一.什么是泛型: 泛型的本质是 参数化类型,也就是说 将所操作的数据类型 指定为一个参数,在不创建新类的情况下,通过参数来指定所要操作的具体类型(类似于方法中的变量参数,此时类型也定义成参数形式),也 ...

  9. java 泛型 擦除_Java泛型和类型擦除

    一 前言:初识泛型 废话不说,先来看一段代码: public class Holder { private Object data; public Holder(Object data ){ this ...

  10. java什么是类型擦除_Java 泛型,你了解类型擦除吗?

    泛型,一个孤独的守门者. 大家可能会有疑问,我为什么叫做泛型是一个守门者.这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇.泛型是 Java 中一个很小巧的概念,但 ...

最新文章

  1. 织梦文章内容屏蔽替换词语多个敏感字词
  2. 2018年最好用的20个Bootstrap网站模板
  3. 递归计算从1到100之间的所有数之和。
  4. LINQ to SQL之Step by Step及新手问题小结
  5. matlab std函数_如何利用Matlab进行小波分析
  6. java编程技巧_Java编程技巧
  7. 说说单节点集群里安装hive、3\5节点集群里安装hive的诡异区别(版本搭配)
  8. oracle 数据库文件丢失
  9. 用动态规划解小朋友分糖问题
  10. windows xp sp3 原版收藏。
  11. Au 音频效果参考:振幅和压限
  12. android充电线排序,安卓数据线分类有哪些
  13. 获取第二天凌晨12点时间
  14. Android拍照,照片会自己旋转
  15. Vivado安装使用【Verilog】
  16. 修改服务器端Apache默认根目录
  17. LR脚本录制3——Fiddler生成LR脚本(推荐)
  18. NXP-MPC5748G车载MCU使用(食用)方法(踩坑)实用指南(骗人教程)(一):创建工程与导入
  19. 设计师们都在用的3D软件汇总,确定不来学学嘛
  20. unity3d答题系统

热门文章

  1. EasyUI 1.4.4 DataGrid(大数据量) bufferview滚动时不加载下一页数据解决方案
  2. 北大oj-1423- Big Number
  3. [C#] C#访问数据库的代码(Access版本)
  4. 内存管理之memblock探寻
  5. generic_make_request函数处理bio流程分析
  6. FRR BGP协议分析15 -- 路由策略
  7. linux内核分析及应用 -- 文件系统
  8. Linux虚拟文件系统之文件打开(sys_open())
  9. 以snull为例分析linux网卡驱动的技术文档[转载]二
  10. linux mint xmind运行,linux安装Xmind的经验