上篇博文java方法调用之重载、重写的调用原理(一) 讨论了重写与重载的实现原理,这篇博文讨论下单分派与多分派。

单分派、多分派

方法的接收者和方法的参数统称为方法的宗量。 根据分派基于宗量多少(接收者是一个宗量,参数是一个宗量),可以将分派分为单分派和多分派。单分派是指根据一个宗量就可以知道调用目标(即应该调用哪个方法),多分派需要根据多个宗量才能确定调用目标。
请看示例:

/*** Created by fan on 2016/3/29.*/
public class Dispatcher {static class QQ {}static class _360 {}public static class Father {public void hardChoice(QQ arg) {System.out.println("father choose QQ");}public void hardChoice(_360 arg) {System.out.println("father choose _360");}}public static class Son extends Father {@Overridepublic void hardChoice(QQ arg) {System.out.println("son choose QQ");}@Overridepublic void hardChoice(_360 arg) {System.out.println("son choose 360");}}public static void main(String[] args) {Father father = new Father();Father son = new Son();father.hardChoice(new _360());son.hardChoice(new QQ());}
}

执行结果如下所示:

字节码指令如下所示:

public static void main(java.lang.String[]);Code:Stack=3, Locals=3, Args_size=10:   new     #2; //class Dispatcher$Father3:   dup4:   invokespecial   #3; //Method Dispatcher$Father."<init>":()V7:   astore_18:   new     #4; //class Dispatcher$Son11:  dup12:  invokespecial   #5; //Method Dispatcher$Son."<init>":()V15:  astore_216:  aload_117:  new     #6; //class Dispatcher$_36020:  dup21:  invokespecial   #7; //Method Dispatcher$_360."<init>":()V24:  invokevirtual   #8; //Method Dispatcher$Father.hardChoice:(LDispatcher$_360;)V27:  aload_228:  new     #9; //class Dispatcher$QQ31:  dup32:  invokespecial   #10; //Method Dispatcher$QQ."<init>":()V35:  invokevirtual   #11; //Method Dispatcher$Father.hardChoice:(LDispatcher$QQ;)V38:  return

从上面的字节码指令中可以看到,两次方法调用

        father.hardChoice(new _360());son.hardChoice(new QQ());

对应的字节码指令都是一样的,只是参数不同而已:

   24:  invokevirtual   #8; //Method Dispatcher$Father.hardChoice:(LDispatcher$_360;)V35:  invokevirtual   #11; //Method Dispatcher$Father.hardChoice:(LDispatcher$QQ;)V

由此可见,在class文件中都是调用Father的hardChoice()方法。

解析

在java源代码进行编译的过程中,发生了这么个事情。
首先确定方法的接收者,发现两个对象变量的静态类型都是Father类型的,因此在class文件中写的Father类中方法的符号引用。
再者,对于方法参数,一个是_360对象,一个是QQ对象,按照静态类型匹配的原则,自然找到各自的方法。
上面的两步都是在编译器中做出的,属于静态分派,在选择目标方法时根据了两个宗量,是多分派的。因此,静态分派属于多分派类型。
当java执行时,当执行到son.hardChoice(new QQ()); 时,发现son的实际类型是Son,因此会调用Son类中的方法。在执行father.hardChoice(new _360()); 时也有这个过程,只不过father的实际类型就是Father而已。发现,在目标选择时只依据了一个宗量,是单分派的。因此,动态分派属于单分派类型。

结论

到目前为止,java语言是一个静态多分派,动态单分派的语言。下篇博文,将讨论讨论动态分派(即多态)的实现原理 java方法调用之动态调用多态(重写override)的实现原理——方法表(三) 。

参考资料

  • 周志明 《深入理解JAVA虚拟机》

java方法调用之单分派与多分派(二)相关推荐

  1. java方法调用之动态调用多态(重写override)的实现原理——方法表

    转自:http://blog.csdn.net/fan2012huan/article/details/51007517 上两篇篇博文讨论了java的重载(overload)与重写(override) ...

  2. JAVA方法调用中的解析与分派

    JAVA方法调用中的解析与分派 本文算是<深入理解JVM>的读书笔记,参考书中的相关代码示例,从字节码指令角度看看解析与分派的区别. 方法调用,其实就是要回答一个问题:JVM在执行一个方法 ...

  3. java方法调用机制_Java方法调用机制 - osc_bkdv2it5的个人空间 - OSCHINA - 中文开源技术交流社区...

    最近在编程时,修改方法传入对象的对象引用,并没有将修改反映到调用方法中.奇怪为什么结果没有变化,原因是遗忘了Java对象引用和内存分配机制.本文介绍3个点: ① 该问题举例说明 ② 简要阐述Java内 ...

  4. java调用方法出现i 2a_性能-Java方法调用与使用变量

    性能-Java方法调用与使用变量 最近,我与团队负责人就使用临时变量与调用getter方法进行了讨论. 很长时间以来,我一直认为,如果我必须多次调用一个简单的getter方法,我会将其放入一个temp ...

  5. 揭密 Java方法调用的底层原理

    关注公众号"java后端技术全栈" 回复"000"获取优质面试资料 大家好,我是老田,今天来和大家聊聊Java方法调用的底层原理. 我们在日常开发中,其实很少去 ...

  6. java 方法调用绑定

    将一个方法调用同一个方法主体关联起来被称作绑定.若在程序执行前进行绑定(由编译器和连接器实现),叫做前期绑定.读者可能从来没有听说过这个术语,因为它在面向过程语言中不需要选择就默认的绑定方式.例如C语 ...

  7. dalvik对于Java方法调用的实现

    (入口一)字节码OP_INVOKE_ (汇编实现) 1.dvmResolveMethod:(C函数)决议方法的Method :方法名字字符串找ClassObject中Method 2.(设置调用环境) ...

  8. java方法中与参数怎么调用_与Java方法调用中的类型参数有关的问题

    Java 8的Java语言规范在"示例4.11-1.类型的用法"中提供了一个带有类型实参的方法调用示例: void loop(S s) { this.loop(s); // is ...

  9. jsp java方法调用_jsp怎么调用java方法

    jsp调用java的方法:首先在JSP页面中引入Java方法所在的包:然后在页面中编写[]并保存运行即可. 其实非常简单,因为在jsp中可以直接进行Java程序的编写,所以调用Java的方法只需一点点 ...

最新文章

  1. c++ 二分查找的函数 lower_bound upper_bound binary_search
  2. qt之qml开发优缺点_linux配置vlc-qt
  3. 阿里云ECS——Linux连接错误[Read from socket failed: Connection reset by peer]解决方案
  4. :/index.php,http://localhost/my/INDEX.PHP/INDEX/INDEX无法正常运行:解决时找不到Options FollowSymLinks谢谢...
  5. 大数据时代的技术hive:hive介绍
  6. Spark内存管理(1)—— 静态内存管理
  7. oracle 11g 备份导入12c,关于12C版本导出导入11G版本的这点事
  8. 数据库基础:什么是行?什么是主键?
  9. 应该如何理解mobx_MobX入门
  10. php人才招聘cms,骑士cms-php+mysql高效人才招聘系统
  11. 解决allegro 中OUT OF DATE SHAPES问题
  12. 支付宝InfoStr怎么获取
  13. Qt QString().sprintf(“%x“)解决打印无符号十六位数
  14. php7.3 7.4,PHP 7.4 早期性能基准测试:与 7.3 差不多
  15. 我的世界android制作教程,我的世界手机版红石教程 十进二编码器制作方法攻略...
  16. SSO单点登录-基于cookie的单点登录
  17. python动态与静态语言_Python编程笔记--动态属性
  18. Ad Hoc网络路由协议
  19. 骂人的到底是些什么人
  20. 打印机有重影 校正对齐喷头

热门文章

  1. 经常忘记的--jsp被转成servlet放在哪个目录下呢 2、日志路径3、AdminServer.lok
  2. 二维数组查找数字--C语言
  3. 「.XD 文件 」用什么软件打开?
  4. 用计算机画磁化曲线方法,试验铁磁材料的静态磁化曲线测量试验目的学习用电子积分.DOC...
  5. 寻找生成元问题解决(Digit Generator,ACM/ICPC Seoul 2005, UVa1583)
  6. uniApp H5唤醒App
  7. 【实践】多径效应CIR估计
  8. Freebsd + wine1.1.9 + 国元网上证券交易(通达信版)
  9. bem什么意思_管壳式换热器BEM什么意思
  10. 开发者分享 | AXI 基础第 2 讲-使用AXI VIP 对 AXI4-Lite 主 (Master) 接口进行仿真