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. 文件和Variant的转换

    function FileToVariant(FileName: String): OleVariant; var   AStream: TFileStream;   MyBuffer: Pointe ...

  2. spring 整合 hibernate xml配置

    spring 整合 hibernate: hibernate :对数据库交互 spring: ioc   aop 整合点: 1.sessionFactory对象不再由hibernate生成,交由spr ...

  3. conductor Workflow Metrics

    Server Metrics conductor使用spectator收集指标.https://github.com/Netflix/spectator 名称 目的 标签 workflow_serve ...

  4. Maven 基础配置

    pom.xml基础配置: maven中,最让我迷惑的还是那一堆配置! 就拿这个属性配置来说: <properties> <project.build.sourceEncoding&g ...

  5. 安装RabbitMq-----windows

    在官网download我们所需要的版本,安装rabbitMq需要erlang支持 rabbitMq :http://www.rabbitmq.com/download.html erlang  :ht ...

  6. ASP.NET中的URL编码解码(转)

    在对URL进行编码时,该用哪一个?这两都使用上有什么区别吗?测试: string file="文件上(传)篇.doc";string Server_UrlEncode=Server ...

  7. MySQL中执行sql语句错误 Error Code: 1093. You can't specify target table 'car' for update in FROM clause

    MySQL中执行sql语句错误 Error Code: 1093. You can't specify target table 'car' for update in FROM clause 201 ...

  8. boost x64 lib

    libboost_atomic-vc150-mt-gd-x64-1_66.liblibboost_atomic-vc150-mt-s-x64-1_66.liblibboost_atomic-vc150 ...

  9. Spring框架的事务管理相关的类和API

    1. PlatformTransactionManager接口 -- 平台事务管理器.(真正管理事务的类).该接口有具体的实现类,根据不同的持久层框架,需要选择不同的实现类! 2. Transacti ...

  10. DB2锁机制

    相比较Oracle来说,DB2的锁机制麻烦了很多,而且这个麻烦带来的不是性能的上升而是下降,不过如果细致了解的话,只能感慨不愧是数据库理论诞生的公司,在实现数据库理论上比Oracle全面得多.    ...