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的泛型是伪泛型. ...
随机推荐
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 处理静态资源
视频地址:https://www.cctalk.com/v/15114923882788 处理静态资源 无非花开花落,静静. 指定静态资源目录 这里我们使用第三方中间件: koa-static 安装并 ...
- avalon.js 文字显示更多与收起
isShowMore: function (content) { if(content && content.length >= 124){ var shortContent = ...
- SJY摆棋子&&[Violet 3]天使玩偶
SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 [Violet 3]天使玩偶 https://www.lydsy.com/Ju ...
- Birthday(费用流)
Birthday https://www.nowcoder.com/acm/contest/206/A 题目描述 恬恬的生日临近了.宇扬给她准备了一个蛋糕. 正如往常一样,宇扬在蛋糕上插了n支蜡烛,并 ...
- Weblogic 12c 一个domain建多个server(端口)
一.基本概念 我觉得如果刚接触Weblogic,首先应该做的是明白几个基本的概念,可以从一张图入手: 1. 域(domain) 它是一个基本管理单元: 每个域包含一个管理服务器(Administrat ...
- swift - VFL
1.VFL语法总结: //(1)“H”表示水平方向,“V”表示垂直方向 //(2)“|”表示父视图的边界 //(3)“[]”表示这是一个视图UIView的子类,可以组合多个条件,条件用"() ...
- 9-centos定时任务-不起作用- 没指明路径!!!
crond 是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务 工具,并且会自动启动crond进程,cro ...
- Broadcast总结 service
有时候离开应用就会接收不到系统的广播是因为系统默认发送的广播都会有一个参数 ntent startIntent = new Intent();startIntent.putExtra("pk ...
- IBM MQ 学习
import java.io.IOException; import java.util.HashMap; import java.util.Map; import com.ibm.mq.MQC; i ...
- git format-patch 用法【转】
本文转载自:http://blog.csdn.net/xzongyuan/article/details/9425739 git format-patch相对于git diff更便于操作,是更新的打包 ...