看桥方法之前,我们先来看看泛型中类型擦除的概念:

在《java核心卷书卷1》中有这样一段描述:

虚拟机没有泛型类型对象——所有对象都属于普通类。也就是说,虚拟机在执行代码的时候,都会把泛型类翻译成普通的类。

无论何时定义一个泛型类型,都自动提供了一个相应的原始类型(raw type)。原始类型的名字就是删去类型参数后的泛型类型名。擦除(erased)类型变量,并替换为限定类型(无限定的变量用Object)。

下面看一个泛型类:

class Pair<T> {private T first;private T second;public Pair(T first, T second) {super();this.first = first;this.second = second;}public T getFirst() {return first;}public T getSecond() {return second;}
}

它的原始类型是(T没有限定,用Object替换):

class Pair {private Object first;private Object second;public Pair2(Object first, Object second) {super();this.first = first;this.second = second;}public Object getFirst() {return first;}public Object getSecond() {return second;}
}

当然了,一个类型变量或通配符可以有多个限定,例如:T extends Comparable & Serializble。这样的该怎样进行替换呢?原始类型用第一个限定的类型变量来限定。

Eg:

class Pair<T extends Comparable & Serializable> {private T first;private T second;public Pair(T first, T second) {super();this.first = first;this.second = second;}public T getFirst() {return first;}public T getSecond() {return second;}
}

替换完后就变成了(用第一个限定的类型变量Comparable作为原始类型):

class Pair implements Serializable>{private Comparable first;private Comparable second;public Pair(Comparable first, Comparable second) {super();this.first = first;this.second = second;}public Comparable getFirst() {return first;}public Comparable getSecond() {return second;}
}

了解了类型擦除的概念后,看看桥方法的产生:

先看一个例子:

class Father<T> {public void fun(T x) {}
}
class Son extends Father<String> {@Overridepublic void fun(String x) {}
}

Father类和Son类经过类型擦除后变成:

class Father<Object> {public void fun(Object x) {}
}
class Son extends Father {@Overridepublic void fun(String x) {}
}

很显然,子类Son是想覆盖父类Father的fun方法,但是却出现了问题(注意重写的要求:方法名、参数个数和参数类型都必须相同)。因为Father类在编译阶段经过类型擦除后,T被替换成了Object了。也就是Father类中的fun方法变成了:

public void fun(Object x) {
}

这对于多态是个不小的麻烦,考虑下面的代码:

Father<String> f=new Son();
Object x=null;
f.fun(x);

本来是想利用多态调用Son类的fun(Object)方法,但是Son类的却是fun(String),没有fun(Object)方法。这就导致类型擦除和多态产生了冲突。

下面来看看编译器是怎么解决这个问题的:

编译器在Son类中生成了一个桥方法(bridgemethod),我们可以通过javap反编译Son.class文件,看一下:

可以看到确实有两个fun方法:fun(Object)、fun(String)

在生成的桥方法中是怎么操作的呢:

public void fun(Object x){fun((String)x);
}

现在再来看一下f.fun(Object),由于f引用的Son类对象,所以根据多态性质,会调用Son类的fun(Object)方法,这个方法是合成的桥方法。它会去调用Son类的fun(String)方法,这正是我们所期望的结果。

桥方法解决了多态和类型擦除之间的冲突,但是假如Father类中还有一个方法:

public T gun(){///
}

在Son中也想覆盖这个方法呢?

就会发现在Son类中出现了两个方法签名一样的方法(方法名和参数都相同):

public Object gun()
public String gun()

当然,我们是不能这样编写代码的,因为不能有两个名字相同,参数类型也相同却返回不同类型值的方法。

但是,在虚拟机中却是可以的(很神奇),虚拟机用参数类型和返回类型确定一个方法(《java核心卷术卷1》)。编译器可能产生两个仅返回值不同的方法字节码,虚拟机能够正确的处理这一情况。

桥方法不仅用于泛型类,可以看一个例子:

class Person implements Cloneable {@Overridepublic Person clone() throws CloneNotSupportedException {return (Person) super.clone();}
}

在一个方法覆盖另一个方法时,可以指定一个更加严格的返回类型。

实际上Person类也有两个clone方法:

Employee clone()
Object clone()//合成的桥方法,会调用新定义的方法。

总之,需要记住有关Java泛型转换的事实:

1.虚拟机中没有泛型,只有普通的类和方法;

2.所有的类型参数都用他们的限定类型替换;

3.桥方法被用来保持多态;

java泛型--桥方法相关推荐

  1. java 泛型--桥方法

    因为 java 在编译源码时, 会进行 类型擦除, 导致泛型类型被替换限定类型(无限定类型就使用 Object). 因此为保持继承和重载的多态特性, 编译器会生成 桥方法. 本文最后附录所有源码. P ...

  2. java泛型——桥方法

    [0]README 0.1)以下内容转自: http://www.cnblogs.com/ggjucheng/p/3352519.html [1]泛型约束和局限性-- 类型擦除所带来的麻烦 1.1)继 ...

  3. java桥_java 泛型--桥方法

    因为 java 在编译源码时, 会进行 类型擦除, 导致泛型类型被替换限定类型(无限定类型就使用 Object). 因此为保持继承和重载的多态特性, 编译器会生成 桥方法. 本文最后附录所有源码. P ...

  4. Java泛型用于方法,类和接口

    什么是泛型? 型就是数据类型参数化.就是说原本定死的数据类型像方法中的形参一样,数据是不确定的,使用的时候由人传进去,泛型就是这样,数据类型不确定了.使用的时候再确定就可以了. 泛型的特点 是JDK1 ...

  5. Java 泛型实现方法 — 擦拭法

    所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的. 例如,我们编写了一个泛型类Pair,这是编译器看到的代码: public class Pair<T> {private ...

  6. java泛型关于方法返回值前面的T是什么?

    public <T> Test<String,T> setCacheObject(String key,T value){return null; } 前面的T的声明,跟类后面 ...

  7. java 泛型调用方法调用_java – 如何使用泛型调用最具体的方法?

    有以下示例: public class Test { public static class A {} public static void main(String[] args) { A a = n ...

  8. 3万字死磕Java泛型所有细节知识点,看这一篇就够了

    1 泛型 1.0 前言--为什么要死磕Java泛型 不知道阅读这篇文章的你是否曾跟我一样,在没有阅读<Java核心技术>前查阅了大量的Java泛型文章,但是在实际使用泛型的过程中,总是觉得 ...

  9. java 泛型 默认值_java泛型 Java泛型的入门知识

    在学习java的过程当中,我们就肯定会接触到java泛型,那么你知道java泛型是什么吗,有关java的使用方法又有哪些呢?今天小编就从java泛型的使用方法来了解一下java泛型这一知识. java ...

最新文章

  1. R基于H2O包构建深度学习模型实战
  2. .NET FrameWork 4.0 新特性
  3. Java基础之Hibernate
  4. [Modules]PrestaShop插件 模块 – 产品推荐模块 随机展示推荐产品
  5. Qt C++属性类型提供给 QML调用(二)
  6. html右侧分为两个框架,html – 两个框架一个滚动条
  7. 【ES】Es使用 报错 TransportClient llegalstateException : Unsupported transport.type [netty3]
  8. java蛮力法解决任务分配问题_【算法题】任务分配问题---匈牙利算法
  9. C#.Net工作笔记011---c# visual studio中的assembly理解
  10. [jquery] 图片热区随图片大小自由缩放
  11. C C++编程子资料库(小程序)
  12. 整流八--电网不平衡状态下三相PWM整流器的控制策略
  13. (二三)计算机组成原理笔记整理之系统总线(总线判优方式,标准传输率,数据总线,地址总线与MDR,MAR的关系等)
  14. Windows下Zookeeper启动错误Invalid arguments, exiting abnormally
  15. LINUX PPP拨号永久在线保障机制
  16. 打击感在动作游戏中如何实现?【战斗篇】
  17. 30岁前不必在乎的30件事
  18. 九号公司第三季营收28亿:小米定制产品分销收入3亿同比降59%
  19. OSPF协议基本原理笔记
  20. 普通台式机上Tesla M40显卡paddleGPU深度学习柯南的变身器上机体验

热门文章

  1. PostMan管理EZ
  2. 安装软件时,“Windows Installer Coordinator”一直循环
  3. 竟然是 300 万的诈骗案!
  4. Uncaught TypeError: XXX is not a function问题解决
  5. 人生有两种境界:一是痛而不言,二是笑而不语(zt)
  6. 【十分钟读懂系列】之什么是SLF,PSL,MLF,SLO?
  7. Hexo 搭建个人博客 基础配置及实操
  8. javaweb商城实现在线支付
  9. 怎样把图片保存为html文件,在Word中通过把编辑的图片另存为HTML文件实现转换图片...
  10. iOS info.plist访问权限设置