java 泛型的类型擦除和桥方法
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 泛型的类型擦除和桥方法的更多相关文章
- java 泛型的类型擦除与桥方法
		
泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...
 - Java中的类型擦除与桥方法
		
类型擦除 Java在语法中虽然存在泛型的概念,但是在虚拟机中却没有泛型的概念,虚拟机中所有的类型都是普通类.无论何时定义一个泛型类型,编译后类型会被都被自动转换成一个相应的原始类型. 比如这个类 pu ...
 - Java泛型:类型擦除
		
类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...
 - Java泛型之类型擦除
		
类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦): ...
 - Java泛型-类型擦除
		
一.概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变 ...
 - 转:有关Java泛型的类型擦除(type erasing)
		
转载自:拈花微笑 自从Java 5引入泛型之后,Java与C++对于泛型不同的实现的优劣便一直是饭后的谈资.在我之前的很多training中,当讲到Java泛型时总是会和C++的实现比较,一般得出的结 ...
 - JAVA 泛型之类型擦除
		
★ 泛型是 JDK 1.5 版本引进的概念,之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容. CollectionTest.java ---编译成CollectionTest. ...
 - Java泛型的类型擦除
		
package com.srie.testjava; import java.util.ArrayList; import java.util.List; public class TestGener ...
 - Java泛型类与类型擦除
		
转载自:http://blog.csdn.net/lonelyroamer/article/details/7868820 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型. ...
 
随机推荐
- 文件和Variant的转换
			
function FileToVariant(FileName: String): OleVariant; var AStream: TFileStream; MyBuffer: Pointe ...
 - spring 整合 hibernate xml配置
			
spring 整合 hibernate: hibernate :对数据库交互 spring: ioc aop 整合点: 1.sessionFactory对象不再由hibernate生成,交由spr ...
 - conductor Workflow Metrics
			
Server Metrics conductor使用spectator收集指标.https://github.com/Netflix/spectator 名称 目的 标签 workflow_serve ...
 - Maven 基础配置
			
pom.xml基础配置: maven中,最让我迷惑的还是那一堆配置! 就拿这个属性配置来说: <properties> <project.build.sourceEncoding&g ...
 - 安装RabbitMq-----windows
			
在官网download我们所需要的版本,安装rabbitMq需要erlang支持 rabbitMq :http://www.rabbitmq.com/download.html erlang :ht ...
 - ASP.NET中的URL编码解码(转)
			
在对URL进行编码时,该用哪一个?这两都使用上有什么区别吗?测试: string file="文件上(传)篇.doc";string Server_UrlEncode=Server ...
 - 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 ...
 - boost x64 lib
			
libboost_atomic-vc150-mt-gd-x64-1_66.liblibboost_atomic-vc150-mt-s-x64-1_66.liblibboost_atomic-vc150 ...
 - Spring框架的事务管理相关的类和API
			
1. PlatformTransactionManager接口 -- 平台事务管理器.(真正管理事务的类).该接口有具体的实现类,根据不同的持久层框架,需要选择不同的实现类! 2. Transacti ...
 - DB2锁机制
			
相比较Oracle来说,DB2的锁机制麻烦了很多,而且这个麻烦带来的不是性能的上升而是下降,不过如果细致了解的话,只能感慨不愧是数据库理论诞生的公司,在实现数据库理论上比Oracle全面得多. ...