资讯专栏INFORMATION COLUMN

bridgeMethod In Java

alaege / 1096人阅读

摘要:为什么需要源语言与虚拟机存在语义上的差异中方法指的是方法参数和方法名称完全一致这样的操作称为如果方法参数类型不一致包括参数类型或者参数的顺序不一致这样的操作称为两者在中的判断都不包括返回值类型即返回值类型与两者无关中对于同个方法名不同的与都

1.为什么需要bridgeMethod

Java(Java源语言)与 JVM 虚拟机 存在语义上的差异,JavaOverride方法指的是方法参数和方法名称完全一致.这样的操作称为Override.如果方法参数类型不一致(包括参数类型,或者参数的顺序不一致),这样的操作称为Overloading.两者在Java中的判断都不包括返回值类型return type,即返回值类型与两者无关

JVM中,对于同个方法名,不同的parameter typereturn type 都可以看作Override操作,因为在JVM采用Full-Signature(全方法签名)来校验一个方法的合法性,全体包括method name,parameter type,return type

综上,JavaJVMOverride的语义规则不一致.为了去除语义冲突,同时又不用修改JVM实现的需求下,bridgeMethod应运而生,可以把它看作我们web开发中常见的中间件(中间过程处理)来理解.

2.打破常规

能生成Java字节码的方式有很多 不止在编译器中 如Idea,eclipse等 在编译器中 相同方法名称 不同的返回值编译是不能通过的 但是我们可以通过其他方式来生成符合场景的字节码文件

JVMJava语义不一样,举个生活中的例子,这就好比方言和普通话,Java就是四川方言,JVM就是普通话,四川话:"你吃饭了没得,幺儿",普通话:"你吃饭了吗,儿子 or 女儿"(注意这里的差别).四川方言中,"幺儿"可以是儿子和女儿的统称,这就对应Java中相同method name不区分return type.但是在普通话中,需要指明"儿子"或者是"女儿". 大家都是一个意思,只不过表达方式不一样.普通话是中国话的标准,规则就更严格和细致.为了将方言翻译成普通话能理解的意思,就要去除两者的语义差异,这就是bridgeMethod的意义.

3.API相关

根据reflect的相关方法,我们可以获取一个Object Class的全部定义,包括属性,方法名等等.

根据常规class.getDeclaredMethod(String name,Class...paramterTypes) 可以根据方法名称和参数类型获取class中的方法,但是这个方法对相同方法名不同返回值无效.

可以通过class.getDeclaredMethod()获取全部的方法

MethodHandles.Lookup提供了更丰富更灵活的API,可以根据method name,paramter type,return type的限定条件获取一个方法

4.代码实现

一个接口SuperClass

public interface SuperClass{
    T chifan();
}

一个实现类SubClass

public class SubClass implements SuperClass{
  @Override
  public String chifan(){
    return "幺儿";
  }
} 

JVM中实现类SubClass的代码如下

public class SubClass implements SuperClass{
  @Override
  public String chifan(){
    return "幺儿";//这里是Java方言 幺儿的统称 String类型 是"男孩","女孩" 都行
  }
  
  @Override
  public Object chifan(){
    return (String)"幺儿";//bridgeMethod 将"幺儿"指定为String类型,"男孩",或者是"女孩"
  }
} 

Java中,子类SubClass实现了父类SuperClasschifan()方法,相同的方法名,相同的方法参数列表,相同的方法参数类型,即在Java中,这已经完成了Override重写的语义定义.但是在JVM中,这并不是能够认可的Override行为.有语义冲突.所以创造了一个bridgeMethod方法

本人目前学习到的所有博客,对Java版本有特别印象(学习其他大佬的文章中经常提到的版本)的有3个.从低到高分别是Java5,Java7,Java8,本文中涉及到的技术点主要是Java5Java 1.5以后出现的.所以我们来谈下Java5的版本特性

5.追根溯源 Java5特性

Java5 support covaraint return type 支持可变返回类型,在Java5之前.子类实现的方法名称,方法参数,返回类型都要相同,才叫method Override.具体可以看下篇文章

https://blogs.oracle.com/sund...

Java5以后,只要子类实现方法的返回类型是父类方法返回类型的子类,也可以认作是Override .

Java5以后支持范型,范型的出现是为了减少类型转换异常.将一些运行时才能暴露的问题提前在编译时暴露.可以参见下面的代码

List list=new ArrayList();
list.add("wcl");
list.add(2.50);

上面的代码没有问题,但是并不好,因为指代不明.在Idea中会出现类型未检查的异常.接着来举例.

有一个女老师,带小学生们出去春游.

老师说:"孩子们,老师带你们上厕所,走吧走吧".(规则指定 女老师只能带小女孩去上厕所).可是因为"孩子们"这样的称呼,指代不明,我这样呆萌的小男孩也会跟着老师去上厕所,那这就尴尬了,就会有误入女厕的情况发生.

为了避免这种情况发生.范型出现了.如下

List list=new ArrayList();
list.add("wcl");
list.add(2.50);// error

范型的作用如上所示 就像是女老师的话变为

老师说:"女孩子们,老师带你们上厕所,走吧走吧".这时呆萌的小男孩就不会跟着老师去了.去了就要被教育

本文的bridgeMethod也可以用上面的例子举例.

"孩子们,老师带你们上厕所" 这是Java中的语义

"孩子们,老师带你们上男厕所"这是JVM中的语义

看起来 范型的使用就是规则限定前置 bridgeMethod的使用 就是规则限定后置 两者有异曲同工之妙

6.结语

最近学习大佬的 SpringMVC:源代码分析与实现 里面的 BridgeMethodResolver 然后学习了bridgeMethod 以上都是本人看博客的一些总结 然后用自认为容易理解的形式 和 本人学习过程中模糊点的解释 .特别是第2点,我总以为JavaJVM之间语义是一致的,或许更准确的说,我一直都不知道JavaJVM存在语义差异.所以看一些质量不高的博客后总有一种似懂非懂的感觉.学技术应该知其然更知其所以然.如果有问题,请大佬们指正.帮助我进步.谢谢.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74895.html

相关文章

  • ABAP SICF服务和Java Servlet的比较

    In my opinion ABAP ICF handler and Java Servlet play the same role in enhancement which enables your web server with additional functionality. This blog will not introduce how an ICF handler class in ...

    Youngs 评论0 收藏0
  • Java/CORBA

    摘要:实现的功能有登录注册保存有一个成员变量所有的注册用户使用一个来管理,登录注册都是对的操作保存是将序列化到本地的文件,通过读取文件来反序列化,实现数据的持久化实现的功能有添加查询删除清除保存。 本文HelloCorba参考 Getting Started with JavaTM IDL 说在前面 Java TM IDL is a technology for distributed ob...

    masturbator 评论0 收藏0
  • 基于java的IO流的文件读取系统

    摘要:流读写基本功能新建文件查看列表写文件删除文件查看文件导入的包下面新建一个类,然后在函数里初始化一个方法,方法中用来判断输入的值所相对应的功能板块。这里也只限制于在正常情况下的输入输出。 IO流读写 基本功能: 新建文件 查看列表 写文件 删除文件 查看文件 导入的包: import java.io.BufferedInputStream; import java.io.Buffe...

    chunquedong 评论0 收藏0
  • Java™ 教程(创建和使用包)

    包 本课程解释了如何将类和接口捆绑到包中,如何使用包中的类,以及如何安排文件系统以便编译器可以找到源文件。 创建和使用包 为了使类型更易于查找和使用,避免命名冲突和控制访问,程序员将相关类型的组捆绑到包中。 定义:包是一组提供访问保护和名称空间管理的相关类型,请注意,类型引用类、接口、枚举和注解类型,枚举和注解类型分别是特殊的类和接口,因此在本课中通常将类型简称为类和接口。 作为Java平台一部...

    617035918 评论0 收藏0
  • 线上问题排查常见脚本工具

    摘要:从所有的进程中找出最消耗的线程缺省个,打印出其线程栈用法要显示的线程栈数要显示的线程栈数指定的脚本找出库,即文件或目录类目录中的重复类。通过脚本参数指定目录,查找目录下文件,收集文件中文件以分析重复类。 show-busy-java-threads.sh 从所有的 Java 进程中找出最消耗 CPU 的线程(缺省5个),打印出其线程栈 用法 ./show-busy-java-threa...

    vvpvvp 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<