javac之BridgeMethod及泛型擦除重写
When compiling a class or interface that extends a parameterized class or implements a parameterized interface, the compiler may need to create a synthetic method, called a bridge method, as part of the type erasure process. You normally don't need to worry about bridge methods, but you might be puzzled if one appears in a stack trace.
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);
}
}
After type erasure, the Node and MyNode classes become:
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;
}
}
class MyNode extends Node {
public MyNode(Integer data) {
super(data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
/*synthetic*/ public void setData(Object x0) {
this.setData((Integer)x0);
}
}
After type erasure, the method signatures do not match. The Node method becomes setData(Object) and the MyNode method becomes setData(Integer). Therefore, the MyNodesetData method does not override the Node setData method.
To solve this problem and preserve the polymorphism of generic types after type erasure, a Java compiler generates a bridge method to ensure that subtyping works as expected. For the MyNode class, the compiler generates the following bridge method for setData:
class MyNode extends Node {
// Bridge method generated by the compiler
//
public void setData(Object data) {
setData((Integer) data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
// ...
}
As you can see, the bridge method, which has the same method signature as the Node class's setData method after type erasure, delegates to the original setData method.
下面来看个泛型擦除重写的例子,如下:
class Cell<A> {
A value;
}
class Test {
public void t() {
Cell<Integer> cell = null;
Object x1 = cell.value;
Integer x2 = cell.value;
int x3 = cell.value;
long x4 = cell.value;
}
}
最后必定为如下的格式:
class Test {
Test() { }
public void t() {
Cell<Integer> cell = null;
Object x1 = ((Cell)cell).value;
Integer x2 = (Integer)((Cell)cell).value;
int x3 = ((Integer)((Cell)cell).value).intValue();
long x4 = (long)((Integer)((Cell)cell).value).intValue();
}
}
参考:
(1)http://www.baeldung.com/java-type-erasure
javac之BridgeMethod及泛型擦除重写的更多相关文章
- Java中泛型区别以及泛型擦除详解
一.引言 复习javac的编译过程中的解语法糖的时候看见了泛型擦除中的举例,网上的资料大多比较散各针对性不一,在此做出自己的一些详细且易懂的总结. 二.泛型简介 泛型是JDK 1.5的一项新特性,一种 ...
- 泛型深入--java泛型的继承和实现、泛型擦除
泛型实现类: package generic; /** * 泛型父类:子类为“富二代”:子类的泛型要比父类多 * 1,保留父类的泛型-->子类为泛型类 * 2,不保留父类泛型-->子类按需 ...
- 关于Java泛型"擦除"的一点思考
头次写博客,想说的东西不难,关于泛型的疑问,是前一阵在学习jackson中遇到的. 下面就把我所想到的.遇到的,分享出来. 泛型是JDK1.5后的一个特性,是一个参数类型的应用,可以将这个参数声明在类 ...
- java中的伪泛型---泛型擦除(不需要手工强转类型,却可以调用强转类型的方法)
Java集合如Map.Set.List等所有集合只能存放引用类型数据,它们都是存放引用类型数据的容器,不能存放如int.long.float.double等基础类型的数据. 使用反射可以破解泛型T类型 ...
- 深入理解泛型之JAVA泛型的继承和实现、泛型擦除
很多的基础类设计会采用泛型模式,有些应用在使用的时候处于隔离考虑,会进行继承,此时子类如何继承泛型类就很讲究了,有些情况下需要类型擦除,有些情况下不需要类型擦除,但是大多数情况下,我们需要的是保留父类 ...
- [转] Java 的泛型擦除和运行时泛型信息获取
原文链接 https://my.oschina.net/lifany/blog/875769 前言 现在很多程序员都会在简历中写上精通 Java.但究竟怎样才算是精通 Java 呢?我觉得不仅要熟练掌 ...
- Java笔记——泛型擦除
1. 泛型擦除 package cn.Douzi.T_Demo; import java.util.ArrayList; /** * @Auther: Douzi * @Date: 2019/3/8 ...
- Java的反射机制与泛型擦除
实现方式 反编译:.class–>.java 通过反射机制访问java对象的属性,方法,构造方法等涉及类 java.lang.Class; java.lang.reflect.Construct ...
- Java泛型擦除
Java泛型擦除: 什么是泛型擦除? 首先了解一下什么是泛型?我个人的理解:因为集合中能够存储随意类型的对象.可是集合中最先存储的对象类型一旦确定后,就不能在存储其它类型的对象了,否则,编译时不会报错 ...
随机推荐
- nodejs中使用mongodb quickstart
nodejs中使用mongodb quickstart node 中使用mongodb的quick start.整理的官网crud简单例子. 在百度找了几篇帖子都有问题,所以直接看官网了. 连接Mon ...
- SharpMap源代码解析
1. 简介 SharpMap是基于.net2.0的GIS系统.支持多种.NET开发语言(C# C++ 等).使用属性数据作为注记.符合OpenGIS的简单要素规范(OpenGIS Simple Fea ...
- 利用backtrace和backtrace_symbols函数打印调用栈信息
在头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈. #include <execinfo.h> int backtrace(void * ...
- CentOS系统安装遇到的一些问题
Vi操作:按ESC键 跳到命令模式,然后: :w 保存文件但不退出vi:w file 将修改另外保存到file中,不退出vi:w! 强制保存,不推出vi:wq 保存文件并退出vi:wq! 强制保存文件 ...
- CS中窗体的基类(BaseForm)注意点
窗体基类最好新建一个窗体(BaseForm) 1.这样能够保证在VS中保证他的派生窗口也能够可视化. 2.如果基类直接是一个cs类文件,对于处理派生窗口就很复杂,比如按钮权限之类的操作; 如果直接继承 ...
- dorado7-HelloWorld
1.首先在Tomat中将 Auto reloding enable去掉,去掉的目的不用每次更改代码,都要重新部署 2.创建dorado视图文件 2.1 视图文件的格式为xml 2.2 在view中添加 ...
- C# GDI绘制仪表盘(纯代码实现)
纯代码实现GDI绘制仪表盘,效果在代码下面. public partial class HalfDashboardUc : UserControl { /// <summary> /// ...
- LiLicense server OR Activation code
JET BRAINS系列工具下载地址: https://www.jetbrains.com/products.html?fromMenu License server 输入下列两个任何一个点击 Act ...
- Python 第三方包上传至 PyPI 服务器
PyPI 服务器主要功能是?PyPI 服务器怎么搭建? PyPI 服务器可以用来管理自己开发的 Python 第三包. Pypi服务器搭建 Python 第三方包在本地打包 # 本地目录执行以下命令应 ...
- linux crontab 实现每秒执行的实例
linux crontab 命令,最小的执行时间是一分钟.如需要在小于一分钟内重复执行,可以有两个方法实现. 1.使用延时来实现每N秒执行 原理:通过延时方法 sleep N 来实现每N秒执行. 创 ...