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

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

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

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

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

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

泛型类型擦除

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

考虑下面的泛型类:  

 public class Node<T> {

     private T data;
private Node<T> next; public Node(T data, Node<T> next) }
this.data = data;
this.next = next;
} public T getData() { return data; }
// ...
}

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

  public class Node {

     private Object data;
private Node next; public Node(Object data, Node next) {
this.data = data;
this.next = next;
} public Object getData() { return data; }
// ...
}

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

  public class Node<T extends Comparable<T>> {

     private T data;
private Node<T> next; public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
} public T getData() { return data; }
// ...
}

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

 public class Node {

     private Comparable data;
private Node next; public Node(Comparable data, Node next) {
this.data = data;
this.next = next;
} public Comparable getData() { return data; }
// ...
}

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

类型擦除的影响和桥方法

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

给定以下两个类:

 public class Node<T> {

     public T data;

     public Node(T data) { this.data = data; }

     public void setData(T data) {
System.out.println("Node.setData");
this.data = data;
}
} public class MyNode extends Node<Integer> {
public MyNode(Integer data) { super(data); } public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}

考虑以下代码:

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

类型擦出后,代码变成

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

     public Object data;

     public Node(Object data) { this.data = data; }

     public void setData(Object data) {
System.out.println("Node.setData");
this.data = data;
}
} public class MyNode extends Node { public MyNode(Integer data) { super(data); } public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}

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

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

 class MyNode extends Node {

     // 编译器生成的桥方法
//
public void setData(Object data) {
setData((Integer) data);
} public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
} // ...
}

java 泛型的类型擦除和桥方法的更多相关文章

  1. java 泛型的类型擦除与桥方法

    泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...

  2. Java中的类型擦除与桥方法

    类型擦除 Java在语法中虽然存在泛型的概念,但是在虚拟机中却没有泛型的概念,虚拟机中所有的类型都是普通类.无论何时定义一个泛型类型,编译后类型会被都被自动转换成一个相应的原始类型. 比如这个类 pu ...

  3. Java泛型:类型擦除

    类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...

  4. Java泛型之类型擦除

    类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦): ...

  5. Java泛型-类型擦除

    一.概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变 ...

  6. 转:有关Java泛型的类型擦除(type erasing)

    转载自:拈花微笑 自从Java 5引入泛型之后,Java与C++对于泛型不同的实现的优劣便一直是饭后的谈资.在我之前的很多training中,当讲到Java泛型时总是会和C++的实现比较,一般得出的结 ...

  7. JAVA 泛型之类型擦除

    ★ 泛型是 JDK 1.5 版本引进的概念,之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容. CollectionTest.java ---编译成CollectionTest. ...

  8. Java泛型的类型擦除

    package com.srie.testjava; import java.util.ArrayList; import java.util.List; public class TestGener ...

  9. Java泛型类与类型擦除

    转载自:http://blog.csdn.net/lonelyroamer/article/details/7868820 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型. ...

随机推荐

  1. .Spark Streaming(上)--实时流计算Spark Streaming原理介

    Spark入门实战系列--7.Spark Streaming(上)--实时流计算Spark Streaming原理介绍 http://www.cnblogs.com/shishanyuan/p/474 ...

  2. oracle 查看被锁的表和解锁

    相关视图 SELECT * FROM v$lock;SELECT * FROM v$sqlarea;SELECT * FROM v$session;SELECT * FROM v$process ;S ...

  3. etcd ui

    https://github.com/henszey/etcd-browser docker build --build-arg http_proxy=http://109.105.4.17:3128 ...

  4. Nsis Sqlite Plugin

    1.https://stackoverflow.com/questions/15346338/nsis-and-sqlite-integration 2.http://nsis.sourceforge ...

  5. JDA 8.0.0.0小版本升级

    一.升级前关服务和进行备份 二.开始升级 三. 开以下四个服务 1237 四个服务开启后需重新执行SSIS中的startingFP(去掉backupdata 05 importFP) 当以下值为0,代 ...

  6. Zabbix 监控端口状态并邮件报警

    Zabbix监控端口 前提 zabbix安装 zabbix邮件报警 添加监控项 添加触发器 添加动作 设置完成后,在配置过报警媒介后也就是 邮件报警  后就完成了.

  7. ios 工具大全,最全框架

    https://www.jianshu.com/p/e280f3348156 [链接]文件分享 - 网盘分享https://share.weiyun.com/5A1aura

  8. Python学习day5作业

    目录 Python学习day5作业 ATM和购物商城 1. 程序说明 2. 基本流程图 3. 程序测试帐号 4. 程序结构: 5. 程序测试 title: Python学习day5作业 tags: p ...

  9. Spring boot starter pom的依赖关系说明

    Spring Boot 通过starter依赖为项目的依赖管理提供帮助.starter依赖起始就是特殊的maven依赖,利用了传递依赖解析,把常用库聚合在一起,组成了几个为特定功能而定制的依赖. sp ...

  10. win 下 apache 实现负载均衡

    1.打开apache的配置文件httpd.conf,打开如下项 LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_ajp_mo ...