oracle原文地址:https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

在Java中,泛型的引入是为了在编译时提供强类型检查和支持泛型编程。为了实现泛型,Java编译器应用类型擦除实现:

1、  用类型参数(type parameters)的限定(如果没有就用Object)替换泛型类型中的所有类型参数。

2、  需要保持类型安全的时候插入类型转换(隐含插入)

3、  在extened 泛型类型中生成桥方法来保证多态性

类型擦除确保不会为已参数化了的类型(paramterized types)产生新类,这样泛型能保证没有运行时的负载。

泛型类型擦除

在类型擦除过程中,java编译器擦除所有类型参数,用它的限定或者Object(没限定时)替换。

考虑下面的泛型类:  

 1 public class Node<T> {
 2
 3     private T data;
 4     private Node<T> next;
 5
 6     public Node(T data, Node<T> next) }
 7         this.data = data;
 8         this.next = next;
 9     }
10
11     public T getData() { return data; }
12     // ...
13 }

因为类型参数T是非限定的,Java编译器使用Object替换它:  

 1  public class Node {
 2
 3     private Object data;
 4     private Node next;
 5
 6     public Node(Object data, Node next) {
 7         this.data = data;
 8         this.next = next;
 9     }
10
11     public Object getData() { return data; }
12     // ...
13  }

下面的例子,泛型Node类使用了限定类型参数:

 1  public class Node<T extends Comparable<T>> {
 2
 3     private T data;
 4     private Node<T> next;
 5
 6     public Node(T data, Node<T> next) {
 7         this.data = data;
 8         this.next = next;
 9     }
10
11     public T getData() { return data; }
12     // ...
13 }

编译器会使用第一个限定类,Comparable替换限定参数类型T:

 1 public class Node {
 2
 3     private Comparable data;
 4     private Node next;
 5
 6     public Node(Comparable data, Node next) {
 7         this.data = data;
 8         this.next = next;
 9     }
10
11     public Comparable getData() { return data; }
12     // ...
13 }

同样,泛型方法也可以擦除。规则类似,不细说。

类型擦除的影响和桥方法

有时候类型擦除会引起无法预知的情况。比如:

给定以下两个类:

 1 public class Node<T> {
 2
 3     public T data;
 4
 5     public Node(T data) { this.data = data; }
 6
 7     public void setData(T data) {
 8         System.out.println("Node.setData");
 9         this.data = data;
10     }
11 }
12
13 public class MyNode extends Node<Integer> {
14     public MyNode(Integer data) { super(data); }
15
16     public void setData(Integer data) {
17         System.out.println("MyNode.setData");
18         super.setData(data);
19     }
20 }

考虑以下代码:

1  MyNode mn = new MyNode(5);
2 Node n = mn;            // 原生类型 – 编译器会给出未检查警告
3 n.setData("Hello");
4 Integer x = mn.data;    // 会引发抛出ClassCastException

类型擦出后,代码变成

1 MyNode mn = new MyNode(5);
2 Node n = (MyNode)mn;         //原生类型 – 编译器会给出未检查警告
3 n.setData("Hello");
4 Integer x = (String)mn.data; //会引发抛出ClassCastException

 1 public class Node {
 2
 3     public Object data;
 4
 5     public Node(Object data) { this.data = data; }
 6
 7     public void setData(Object data) {
 8         System.out.println("Node.setData");
 9         this.data = data;
10     }
11 }
12
13 public class MyNode extends Node {
14
15     public MyNode(Integer data) { super(data); }
16
17     public void setData(Integer data) {
18         System.out.println("MyNode.setData");
19         super.setData(data);
20     }
21 }

类型擦除后,方法的签名已经不匹配。Node 方法变成setData(Object),MyNode方法变成setData(Integer)。MyNode setData方法已经不是覆盖Node setData方法。

为了解决这个问题,维持泛型类型的多态性,java编译器会生成一个桥方法:

 1 class MyNode extends Node {
 2
 3     // 编译器生成的桥方法
 4     //
 5     public void setData(Object data) {
 6         setData((Integer) data);
 7     }
 8
 9     public void setData(Integer data) {
10         System.out.println("MyNode.setData");
11         super.setData(data);
12     }
13
14     // ...
15 }

转载于:https://www.cnblogs.com/linghu-java/p/10031239.html

java 泛型的类型擦除和桥方法相关推荐

  1. Java泛型:类型擦除

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

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

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

  3. 泛型中的类型擦除和桥方法

    在Java中,泛型的引入是为了在编译时提供强类型检查和支持泛型编程.为了实现泛型,Java编译器应用类型擦除实现: 1.  用类型参数(type parameters)的限定(如果没有就用Object ...

  4. 泛型之类型擦除和桥接方法

    泛型是将类型参数化,允许定义在类.接口.方法时使用类型参数,当使用的时候指定具体类型.泛型主要应用在集合 泛型的优点 代码需要更精简 程序更加健壮 编码期,可读性很高 泛型的上下限 上限 格式:类型名 ...

  5. Java泛型的类型擦除

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

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

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

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

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

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

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

  9. java中的类型擦除type erasure

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

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

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

最新文章

  1. CentOS-6.5安装配置Tengine
  2. python对象模型映射_看例子,学 Python(三)
  3. JAVA方法重载与构造方法简介
  4. Windows 搭建 .NET 跨平台环境并运行应用程序
  5. NLP学习—21.自注意力机制(Self-Attention)与Transformer详解
  6. Luogu1783 海滩防御
  7. c语言实数的输出和占位_C语言输出格式总结
  8. java digester map_Digester学习笔记
  9. 随机森林回归预测_jupyter notebook
  10. 【excel问题】关于组织策略阻止超链,解决方法
  11. 基于RT-Thread的环境监测装置(含IO口模拟8080时序驱动TFT屏幕)
  12. OPENGL OSG setNearFarRatio可以动态调节远近剪裁面
  13. [转]俞敏洪:我和马云就差了8个字... [来自: news.mbalib.com]
  14. 深度学习在知识图谱的应用
  15. 安卓应用在各大应用市场上架方法
  16. 12月编程语言排行榜公布啦~
  17. 电脑充电器,电脑充电器没带怎么充电
  18. html 自动排序表格,表格排序.html
  19. thymeleaf和Jsp或者HTML有什么区别
  20. Oracle设置主键报错 ORA-02437: 无法验证 (DENGCHAO.TEST) - 违反主键

热门文章

  1. 网络核心之数据交换 - 报文、分组交换3
  2. 实现二叉树的遍历(递归与非递归)
  3. Leetcode 刷题笔记(三) —— 数组类型解题方法三:滑动窗口
  4. Python3实现文件名排序
  5. 杭电计算机2011年硕士研究生笔试详解
  6. Asp.net 无限级分类
  7. 工作中那些有用的工具
  8. CentOS7上squid的部署及两种模式(4.1版本)
  9. Lua5.1 升级 Lua5.3 升级 小结
  10. Guava 相关文章