详解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
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java高并发之CyclicBarrier的用法详解
Springbean的几种注入方式都了解吗
Spring @Transactional注解失效解决方案
Spring boot中@Conditional和spring boot的自动配置实例详解
![](https://img.aspxhome.com/file/2023/9/61539_0s.png)
Java中的javaBean、vo、entity、domain和pojo
![](https://img.aspxhome.com/file/2023/5/61605_0s.png)
java之swing表格实现方法
Minio与SpringBoot使用okhttp3问题解决
![](https://img.aspxhome.com/file/2023/1/83501_0s.jpg)
C#操作串口通信协议Modbus的常用方法介绍
C#利用Label标签控件模拟窗体标题的移动及窗体颜色不断变换效果
![](https://img.aspxhome.com/file/2023/8/79038_0s.jpg)
Struts 2中的constant配置详解
java 中String.equals和==的比较
深入解析Java的Hibernate框架中的一对一关联映射
Spring5新功能@Nullable注解及函数式注册对象
![](https://img.aspxhome.com/file/2023/8/79918_0s.png)
基于WPF实现筛选下拉多选控件
![](https://img.aspxhome.com/file/2023/4/69784_0s.png)
Java的类型擦除式泛型详解
![](https://img.aspxhome.com/file/2023/8/61608_0s.jpg)
基于Java中字符串indexof() 的使用方法
![](https://img.aspxhome.com/file/2023/7/65587_0s.jpg)
Java应用多机器部署解决大量定时任务问题
![](https://img.aspxhome.com/file/2023/1/58691_0s.png)