Java中的类型擦除与桥方法
类型擦除
Java在语法中虽然存在泛型的概念,但是在虚拟机中却没有泛型的概念,虚拟机中所有的类型都是普通类。无论何时定义一个泛型类型,编译后类型会被都被自动转换成一个相应的原始类型。
比如这个类
public class Parent<T>
{
public void sayHello(T value)
{
System.out.println("This is Parent Class, value is " + value);
}
}
在编译后就变成了
public class Parent
{
public void sayHello(Object value)
{
System.out.println("This is Parent Class, value is " + value);
}
}
对类型变量进行替换的规则有两条:
- 若为无限定的类型,如
<T>,被替换为Object - 若为限定类型,如
<T extends Comparable & Serializable>,则用第一个限定的类型变量来替换,在这里被替换为Comparable
桥方法
类型擦除后,就产生了一个奇怪的现象。
假设有一个超类:
public class Parent<T>
{
public void sayHello(T value)
{
System.out.println("This is Parent Class, value is " + value);
}
}
以及一个子类:
public class Child extends Parent<String>
{
public void sayHello(String value)
{
System.out.println("This is Child class, value is " + value);
}
}
最后有以下测试代码,企图实现多态:
public class MainApp
{
public static void main(String[] args)
{
Child child = new Child();
Parent<String> parent = child;
parent.sayHello("This is a string");
}
}
运行的时候,会对Child类的方法表进行搜索,先分析一下Child类的方法表里有哪些东西:
1. sayHello(Object value) : 从类型被擦除后的超类中继承过来
2. sayHello(String value) : 自己新增的方法,和超类毫无联系
3. 一些从Object类继承来的方法,这里忽略
按理来说,这段测试代码应该不能通过编译,因为要实现多态的话,所调用的方法必须在子类中重写,但是在这里Child类并没有重写Parent类中的sayHello(Object value)方法,只是单纯的继承而已,并且新加了一个参数不同的同名方法。
但是结果是可以正常运行。
原因是编译器在Child类中自动生成了一个桥方法:
public void sayHello(Object value)
{
sayHello((String) value);
}
可以看出,这个桥方法实际上就是对超类中sayHello(Obejct)的重写。这样做的原因是,当程序员在子类中写下以下这段代码的时候,本意是对超类中的同名方法进行重写,但因为超类发生了类型擦除,所以实际上并没有重写成功,因此加入了桥方法的机制来避免类型擦除与多态发生冲突。
public class Child extends Parent<String>
{
public void sayHello(String value)
{
System.out.println("This is Child class, value is " + value);
}
}
桥方法并不需要自己手动生成,一切都是编译器自动完成的。
桥方法与Geter
同样的,如果超类中有getter的话,在使用多态的时候也可能发生冲突。假设有超类被类型擦除后存在这样一个方法:
Obejct getValue()
然后在子类中,程序员想要重写这个方法,因此新增了一个这样的方法:
String getValue()
但是正如前面所述,重写并没有起作用,甚至还应该报错,因为在子类中,根据 函数签名=方法名+参数 的原则,从超类继承的方法与新增的方法冲突了。
但实际上这样的代码是可以工作的,原因在于,JVM是用返回值+方法名+参数的方式来计算函数签名的,所以编译器就可以借助这一原则来生成一个桥方法。不过这种计算函数签名的方法仅仅存在于虚拟机中。
Java中的类型擦除与桥方法的更多相关文章
- java 泛型的类型擦除与桥方法
泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...
- java 泛型的类型擦除和桥方法
oracle原文地址:https://docs.oracle.com/javase/tutorial/java/generics/erasure.html 在Java中,泛型的引入是为了在编译时提供强 ...
- Java中泛型 类型擦除
转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...
- Java泛型类与类型擦除
转载自:http://blog.csdn.net/lonelyroamer/article/details/7868820 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型. ...
- c++中的类型擦除
(原创)c++中的类型擦除 c++11 boost技术交流群:296561497,欢迎大家来交流技术. 关于类型擦除,可能很多人都不清楚,不知道类型擦除是干啥的,为什么需要类型擦除.有必要做个说明,类 ...
- Java泛型之类型擦除
类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦): ...
- java中获取日期和时间的方法总结
1.获取当前时间,和某个时间进行比较.此时主要拿long型的时间值. 方法如下: 要使用 java.util.Date .获取当前时间的代码如下 Date date = new Date(); da ...
- Java泛型:类型擦除
类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...
- Java中double类型的数据精确到小数点后两位
Java中double类型的数据精确到小数点后两位 多余位四舍五入,四种方法 一: double f = 111231.5585;BigDecimal b = new BigDecimal(f); d ...
随机推荐
- C++内存布局详解
一个由C/C++编译的程序除了存放函数二进制代码的程序代码段(code段)外,数据占用的内存大致分为以下几个部分: 1.栈区(stack) 存放局部变量.函数参数.返回数据.返回地址等.系统自动分配释 ...
- 实战案例--TEMPDB暴涨
前言 tempdb暴增,造成磁盘空间不足,甚至影响业务运行. 正文 如图,tempdb log文件从7.40开始突然暴涨,因为 tempdb 0 M到 40G tempdb 所 ...
- ssh的相关实验
author:JevonWei 版权声明:原创作品 跨主机ssh连接 主机A想连接主机C,但是主机C防火墙等原因禁止主机A连接,而主机A可以连接主机B,主机B也可连接主机C,即主机A就可通过主机B做跳 ...
- java锁机制
2.4 锁机制 临界区是指,使用同一个锁控制的同一段代码区或多段代码区之间,在同一时间内最多只能有一个线程在执行操作.这个概念与传统的临界区有略微的差别,这里不想强调这些概念上的差别,临 ...
- Project 1 :创建链表与显示链表
目标:创建一个链表,并将链表输出.结构体中包括学号与分数.链表以输入学号为0作为结束.输出模版为 No.学号 Score:分数 输入样例: 10101 98 10102 97 10103 100 10 ...
- 《Java程序设计》终极不改版
半年前的作品,上传只为纪念~ 成绩: ____0.1______ Java程序设计 课程设计 题 目:大学生信息管理系统 学 院: 计算机与软件学院 专 业: 网络工程_____ . ...
- 【★】RSA-什么是不对称加密算法?
不对称加密算法RSA浅析 本文主要介绍不对称加密算法中最精炼的RSA算法.我们先说结论,也就是RSA算法怎么算,然后再讲为什么. 随便选取两个不同的大素数p和q,N=p*q,r=(p-1)*(q-1) ...
- 英语app分析
Andorid 版本 第一部分 调研, 评测 搜索了一下必应跑出来的是微软必应,在印象中微软的产品都是很可靠地.安装之后对它的 排版字体图片等不是很喜欢,感觉有道词典会更亲切一点. 必应 ...
- Java 第六周总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...
- 201521123081《Java程序设计》 第3周学习总结
1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 参考资料:百 ...