详解java 中泛型中的类型擦除和桥方法
作者:lqh 发布时间:2021-07-10 23:55:08
在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);
}
// ...
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
来源:http://blog.csdn.net/Allenalex/article/details/50246985
猜你喜欢
- 本文实例为大家分享了Unity实现俄罗斯方块游戏的具体代码,供大家参考,具体内容如下一、演示二、实现思路创建每一个方块可移动到的位置点,可以
- Mybatis的日志模块的适配器模式我们在开发中日志是必不可少的一部分,而市场中有很多日志框架供我们使用,mybatis作为一个开源框架需要
- Environment的中文意思是环境,它表示整个spring应用运行时的环境信息,它包含两个关键因素profilespropertiesp
- 开篇:我们将前面的springboot整合H2内存数据库,实现单元测试与数据库无关性提供的Restful服务注册到spring cloud的
- 今天,给大家分享一个Java后端利用Phantomjs实现生成图片的功能,同学们使用的时候,可以参考下!PhantomJS简介首先,什么是P
- 这两天因为要做一个随机的地图生成系统,所以一直在研究随机迷宫生成算法,好吧,算是有一点小小的成果。随机迷宫生成我自己的理解简而言之分为以下几
- 前言Zookeeper的通过快照日志和事务日志将内存信息保存下来,记录下来每次请求的具体信息。尤其是其事务日志,每次处理事务请求时都需要将其
- 本文实例讲述了java实现递归文件列表的方法。分享给大家供大家参考。具体如下:FileListing.java如下:import java.
- using System;using System.Collections.Generic;using System.Linq;
- Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。
- 这篇文章主要介绍了通过实例了解Java 8创建Stream流的5种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- C#移除字符串中的不可见Unicode字符 背景最近发现某个数据采集的系统拿下来的数据,有些字段的JSON被莫名截断了,导致后续数
- RFC6749OAuth2的官方文档在RFC6749:https://datatracker.ietf.org/doc/html/rfc67
- 1. 查找1) 顺序查找 SeqSearch.java2) 二分查找【二分法,放在算法讲解】2. 顺序查找有一个数列:白眉鹰王、金毛狮王、紫
- 代码如下所示:using System;using System.Collections.Generic;using System.Text
- springmvc 使用map接收参数开发过程中有时候我们并不知道前端都会传递哪些参数给到后端. 为方便扩展接口功能, 在请求参数不改变的情
- synchronized关键字顾名思义,是用于同步互斥的作用的。这里精简的记一下它的使用方法以及意义:1. 当synchronized修饰
- Timer 详解Timer 和 TimerTask 用于在后台线程中调度任务的 java.
- 单独使用mybatis是有很多限制的(比如无法实现跨越多个session的事务),而且很多业务系统本来就是使用spring来管理的事务,因此
- 项目信息使用SpringBoot web框架,版本号 2.7.10<dependency><groupId>org.