类型擦除

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中的类型擦除与桥方法的更多相关文章

  1. java 泛型的类型擦除与桥方法

    泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...

  2. java 泛型的类型擦除和桥方法

    oracle原文地址:https://docs.oracle.com/javase/tutorial/java/generics/erasure.html 在Java中,泛型的引入是为了在编译时提供强 ...

  3. Java中泛型 类型擦除

    转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...

  4. Java泛型类与类型擦除

    转载自:http://blog.csdn.net/lonelyroamer/article/details/7868820 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型. ...

  5. c++中的类型擦除

    (原创)c++中的类型擦除 c++11 boost技术交流群:296561497,欢迎大家来交流技术. 关于类型擦除,可能很多人都不清楚,不知道类型擦除是干啥的,为什么需要类型擦除.有必要做个说明,类 ...

  6. Java泛型之类型擦除

    类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦): ...

  7. java中获取日期和时间的方法总结

    1.获取当前时间,和某个时间进行比较.此时主要拿long型的时间值. 方法如下:  要使用 java.util.Date .获取当前时间的代码如下 Date date = new Date(); da ...

  8. Java泛型:类型擦除

    类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String& ...

  9. Java中double类型的数据精确到小数点后两位

    Java中double类型的数据精确到小数点后两位 多余位四舍五入,四种方法 一: double f = 111231.5585;BigDecimal b = new BigDecimal(f); d ...

随机推荐

  1. Java起源

    Java历史发展和特点 作为一名合格的程序员,如果不了解一些关于Java语言的起源是有一些不太合适的.下面就介绍一下我所了解的Java起源. 1.Java名字的来源 Java是印度尼西亚爪哇岛的英文名 ...

  2. Grails笔记三:完整的文件上传实例

    文件上传在web应用中是比较普遍的,相对于使用jsp等技术实现文件上传,Grails的文件上传着实让人喜爱,因为极其简单,让人看一遍就容易轻松记住!不多说,实例如下: 假设已有一个名为uploadFi ...

  3. MYSQL 中 LIMIT 用法

    mapper文件中的sql: ------------------------------------------------------------------------------------- ...

  4. jvm 常用内存分析命令

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt121 // 打印出内存占用情况 jstat -gcutil 12564 10 ...

  5. 利用Java调用OpenCV进行人脸识别

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt409 今天我准备学习如何用Java来进行人脸检测.人脸检测有助于在任何数字图 ...

  6. 通过编译lambda表达式来创建实例(可在反射时候用,效率比反射高一些)

    原文地址:https://rogerjohansson.blog/2008/02/28/linq-expressions-creating-objects/ 据说编译lambda创建实例是比反射快.实 ...

  7. JQuery插件制作动态网页

    运用JQuery插件制作动态网页   前  言 JQuery 今天我给大家介绍一个运用JQuery插件制作的动态网页--iphone 5C 宣传页面.这个网页中运用到了fullpage.js和move ...

  8. HTML的基本标签及语法

    一.HTML基本标签head部分 HTML文档的基本结构 <!DOCTYPE html> <html> <head> <meta charset=" ...

  9. 集美大学网络1413第十二次作业成绩(个人作业3) -- Alpha阶段个人总结

    题目 个人作业3--个人总结(Alpha阶段) 优秀作业链接:**068 未交:**087 个人作业3成绩 学号 姓名 总结(4) 5个问题(2.5) 自我评价(2.5) 博客互动 (1) 总分(10 ...

  10. 201521123011 《Java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4-1) 1.1 实验总结 public ...