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

本文最后附录所有源码.

Pair 是个泛型类, 它具有泛型方法 setSecond(T second),
在经过编译时的 类型擦除 后变为 setSecond(Object second).

DateInterval 是 Pair<LocalDate> 的实例化子类, 它具有方法 setSecond(LocalDate second).

在 Main.main 中, 我们新建 DateInterval 对象, 并用基类 Pair<LocalDate> 来引用它,
此时调用基类的 setSecond 方法时, 我们希望它能够实现多态, 即调用 DateInterval.setSecond(LocalDate) 方法.
事实上, java 编译器通过插入 桥方法 的方式, 帮助我们实现了该功能.

反编译 DateInterval.class 会发现它具有两个 setSecond 方法:

  1. void setSecond(LocalDate);
  2. void setSecond(Object).

并且, 在 void setSecond(Object) 中会调用 void setSecond(LocalDate), 这就是所谓的桥方法.

附: DateInterval.class 反编译后的代码:

Compiled from "DateInterval.java"
public class com.book.chapter8.DateInterval extends com.book.chapter8.Pair<java.time.LocalDate> {
public com.book.chapter8.DateInterval();
Code:
0: aload_0
1: invokespecial #1 // Method com/book/chapter8/Pair."<init>":()V
4: return public void setSecond(java.time.LocalDate);
Code:
0: aload_1
1: aload_0
2: invokevirtual #2 // Method getFirst:()Ljava/lang/Object;
5: checkcast #3 // class java/time/chrono/ChronoLocalDate
8: invokevirtual #4 // Method java/time/LocalDate.compareTo:(Ljava/time/chrono/ChronoLocalDate;)I
11: iflt 19
14: aload_0
15: aload_1
16: invokespecial #5 // Method com/book/chapter8/Pair.setSecond:(Ljava/lang/Object;)V
19: return public void setSecond(java.lang.Object);
Code:
0: aload_0
1: aload_1
2: checkcast #6 // class java/time/LocalDate
5: invokevirtual #7 // Method setSecond:(Ljava/time/LocalDate;)V
8: return
}

附: 其他所有源码:

Pair.java:

package com.book.chapter8;

/**
* Created by zhixiao.mzx on 2016/11/5.
*/
public class Pair<T> {
private T first;
private T second; public Pair() {
first = null;
second = null;
} public Pair(T first, T second) {
this.first = first;
this.second = second;
} public T getFirst() {
return first;
} public void setFirst(T first) {
this.first = first;
} public T getSecond() {
return second;
} public void setSecond(T second) {
this.second = second;
}
}

DateInterval.java:

package com.book.chapter8;

import java.time.LocalDate;

/**
* Created by zhixiao.mzx on 2016/11/5.
*/
public class DateInterval extends Pair<LocalDate> {
public void setSecond(LocalDate second) {
if (second.compareTo(getFirst()) >= 0) {
super.setSecond(second);
}
}
}

Main.java:

package com.book.chapter8;

import java.time.LocalDate;

/**
* Created by zhixiao.mzx on 2016/11/5.
*/
public class Main {
public static void main(String[] args) {
DateInterval interval = new DateInterval();
Pair<LocalDate> pair = interval;
pair.setFirst(LocalDate.now());
pair.setSecond(LocalDate.now());
}
}
 
分类: java

java 泛型--桥方法的更多相关文章

  1. JAVA泛型使用方法总结

    1. 基本概念: (1)什么是泛型? 泛型,即"参数化类型".即将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用或 ...

  2. java泛型编译时被擦除引起多态的破坏,用 桥方法解决此类问题。(java 桥方法)

    在JVM虚拟机中泛型编译的时候,会出现类型擦除.但是,在多态场景中,编译时,擦除方式会出现多态被破坏的可能. 举个栗子: A.java public class A<T> { void g ...

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

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

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

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

  5. 0072 Java中的泛型--泛型是什么--泛型类--泛型方法--擦除--桥方法

    什么是泛型,有什么用? 先运行下面的代码: public class Test { public static void main(String[] args) { Comparable c=new ...

  6. Java中的类型擦除与桥方法

    类型擦除 Java在语法中虽然存在泛型的概念,但是在虚拟机中却没有泛型的概念,虚拟机中所有的类型都是普通类.无论何时定义一个泛型类型,编译后类型会被都被自动转换成一个相应的原始类型. 比如这个类 pu ...

  7. 使用java泛型设计通用方法

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...

  8. 初识Java泛型以及桥接方法

    泛型的由来 在编写程序时,可能会有这样的需求:容器类,比如java中常见的list等.为了使容器可以保存多种类型的数据,需要编写多种容器类,每一个容器类中规定好了可以操作的数据类型.此时可能会有Int ...

  9. java泛型应用实例 - 自定义泛型类,方法

    近 短时间需要使用泛型,就研究了下,发现网上的问关于泛型的文章都是讲原理的, 很少有提到那里用泛型比较合适, 本文就泛型类和泛型方法的使用给出两 个典型应用场景. 例如一个toString的泛型方法, ...

随机推荐

  1. 对Java Serializable(序列化)的理解和总结(二)

    遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化 b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化 c,ser ...

  2. [bzoj1019][SHOI2008]汉诺塔 (动态规划)

    Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一个塔状的锥形体. 对汉诺塔的一次合法的操 ...

  3. HDU 5646 DZY Loves Partition 数学 二分

    DZY Loves Partition 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5646 Description DZY loves parti ...

  4. hdu 5204 Rikka with sequence 智商不够系列

    Rikka with sequence Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...

  5. CentOS 6下搭建LAMP环境

    第一步,使用Xshell管理工具连接远程服务器 第二步,输入服务器账号密码登录远程服务器 如果centos内置的yum源可用的软件偏少或者版本过低,请更新! 首先备份/etc/yum.repos.d/ ...

  6. 判断终端是ios还是安卓的一些妙用(附加微信分享图标修改)

    最近遇到一个项目 要求有两个icon(就是下载地址 下载安卓的apk  和ios的安装包) 一开始的方案是 什么设备都显示这两个icon 但是后来老大说这样不好   安卓用户给他下载ios 也不行  ...

  7. Intent 的Flag属性(Activity在栈位置的主宰者)

    Intent 的Flag属性可用来控制Activity在栈中的排列位置,本文列举了常见的Flag. 例--(以无动画方式启动ActivityB): Intent intent=new Intent(A ...

  8. Appium+python自动化18-brew、carthage和appium-doctor

    前言 本篇安装brew.carthage,解决启动appium时的报错问题,另外安装appium-doctor检查appium的环境 1.brew 2.carthage 3.appium-doctor ...

  9. Java操作Microsoft Word之jacob

    转自: 现在我们一起来看看,用Java如何操作Microsoft Word.   jacob,官网是http://danadler.com/jacob 这是一个开源的工具.最新版本1.7     官方 ...

  10. 1503162139-ny-分数拆分

    分数拆分 时间限制:3000 ms  |  内存限制:65535 KB 难度:1 描写叙述 如今输入一个正整数k,找到全部的正整数x>=y,使得1/k=1/x+1/y. 输入 第一行输入一个整数 ...