以下内容来自周志明的《深入理解Java虚拟机》。

前一篇说了静态分派和重载有关,现在的动态分派就和覆盖Override有关了。

先看代码:

public class DynamicDispatch {
static abstract class Human {
protected abstract void sayHello();
} static class Man extends Human {
@Override
protected void sayHello() {
System.out.println("man");
}
} static class WoMan extends Human {
@Override
protected void sayHello() {
System.out.println("woman");
}
} public static void main(String[] args) {
Human man = new Man();
Human woman = new WoMan();
man.sayHello();
woman.sayHello();
man = new WoMan();
man.sayHello();
}
}

结果输出:

man
woman
woman

这里不再根据静态类型来决定,因为静态类型同样都是Human的两个变量man和woman在调用sayHello()方法时执行了不同的行为,因为这两个变量的实际类型不同。

运行期根据实际类型其确定方法执行版本的分派过程称为动态分派。

原书中作者使用了javap命令输出了这段代码的字节码来分析为何是运行时的不同,还讲解了invokevirtual指令的解析步骤,这里就不赘述了。

单分派和多分派

public class Dispatch {
static class QQ {
} static class _360 {
} public static class Father {
public void hardChoice(QQ args) {
System.out.println("father choose qq");
} public void hardChoice(_360 args) {
System.out.println("father choose 360");
}
} public static class Son extends Father {
public void hardChoice(QQ args) {
System.out.println("son choose qq");
} public void hardChoice(_360 args) {
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());
}
}
//输出
father choose 360
son choose qq

java语言的静态分派属于多分派类型,在编译阶段,选择目标方法的依据有两点:

1. 静态类型是Father还是Son

2. 方法参数是QQ还是360

动态分派属于单分派类型,在运行时,执行son.hardChoice(new QQ())这句代码时,由于编译器已经决定目标方法的签名必须为harChoice(QQ),虚拟机不会关系传递过来的参数QQ到底是“腾讯QQ”还是"奇瑞QQ",因为这时参数的静态类型和实际类型都对方法的选择不会构成影响,唯一可以影响虚拟机选择的因为只有方法的接受者的类型是Father还是Son。

再重申一下:静态分派在编译器就完成了,动态分派是运行时才进行的。所以Father son=new Son()这句,虽然静态类型是Father,但是运行后的实际类型是Son,所以son.hardChoice执行的是Son类里的方法而不是Father类里的。

[读书笔记]Java之动态分派的更多相关文章

  1. [读书笔记]Java之静态分派

    以下内容来自周志明的<深入理解Java虚拟机>. 静态分派和重载有关. 先看代码: public static void main(String[] args) { SuperClass ...

  2. 《深入了解java虚拟机》高效并发读书笔记——Java内存模型,线程,线程安全 与锁优化

    <深入了解java虚拟机>高效并发读书笔记--Java内存模型,线程,线程安全 与锁优化 本文主要参考<深入了解java虚拟机>高效并发章节 关于锁升级,偏向锁,轻量级锁参考& ...

  3. [读书笔记]java核心技术

    ps:有时间好好整理下格式.从别的编辑器拷贝过来啥都没了. ~~~~~~~~~~~~~~· 2.java程序设计环境 JDK 开发java使用的软件: JRE 运行java使用的软件: SE 用于桌面 ...

  4. 深入理解java虚拟机读书笔记--java内存区域和管理

    第二章:Java内存区域和内存溢出异常 2.2运行时数据区域 运行时数据区分为方法区,堆,虚拟机栈,本地方法栈,程序计数器 方法区和堆是线程共享的区域 虚拟机栈,本地方法栈,程序计数器是数据隔离的数据 ...

  5. 读书笔记-Java设计模式

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! Java的封装性很好,拿访问控制符来讲,没有权限的类或方法是不能访问的.如public,都可访问:p ...

  6. [读书笔记]Java类载入过程

    一. 类的生命周期 类从被载入到虚拟机内存中開始,到卸载出内存为止,有下面(如图)的生命周期: 以上"载入->验证->准备->解析->初始化"称为类的载入过 ...

  7. 深入理解Java虚拟机读书笔记 -- Java内存区域

    Graal VM: Run Programs Faster Anywhere. 跨语言全栈虚拟机,可以作为"任何语言"的运行平台使用. Java内存结构 程序计数器:线程私有,较小 ...

  8. [读书笔记]java中的volatile关键词

    以下内容大多来自周志明的<深入理解Java虚拟机>. 当一个变量被volatile修饰后,它将具备两种特性: 1. 保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变 ...

  9. [读书笔记]java中的类加载器

    以下内容大多来自周志明的<深入理解Java虚拟机>. 类加载器是java的一项创新,也是java流行的重要原因之一,它最初是为了满足java applet的需求而开发出来. 什么是appl ...

随机推荐

  1. JAVA中最常用的十个快捷键

    http://blog.sina.com.cn/s/blog_5fb39f910101dc2b.html 一个Eclipse骨灰级开发者总结了他认为最有用但又不太为人所知的快捷键组合.通过这些组合可以 ...

  2. MySQL5.5绿色版1067

    mysql的绿色安装版,按照很多文章进行配置,会出现 配置文件里面添加了 [client] default-character-set=utf8 [mysqld] default-character- ...

  3. Ubuntu导入证书

    (*.cer) 首先我们得进入JAVA_HOME目录(查看/etc/profile文件),然后进去以下路径/opt/jdk1.5.0_11/jre/lib/security/ 将证书放进去,假如说是1 ...

  4. koa框架异步返回值的操作(co,koa-compose)

    最近在做demo的时候使用了koa框架,自己做了一个静态服务器,首先判断访问文件是否存在,在回调函数中设置了this.body,run之后,各种404,花了N长的时间把koa-compose和co模块 ...

  5. Android的权限检查

    Application的权限: 可以在AndroidManifest.xml中用<permission>定义运行Application需要的权限. 用<uses-permission ...

  6. c++作业:Circle

    Circle Github链接

  7. powershell读写磁盘变量(对象序列化)

    ---[第一章,开篇引子]--- 很久很久以前,我在网上闲逛,看到一头powershell菜鸟,写了一篇感慨道“挖哈哈,我学会powershell啦,我以前很笨,各种不懂,还想把变量保存起来.” 实际 ...

  8. com.android.internal.os.ZygoteInit$MethodAndArgsCaller 解决

    好久没写博客了,带着点小愧疚来,添上几个字: 这是今天遇到的一个bug,之前也遇到过,为了后面方便,就记下. bug提示:com.android.internal.os.ZygoteInit$Meth ...

  9. 同上 遍历obj的值 来定义当前的后台数据在页面的定位

    function getlistRoom(obj) { //obj就是通过ajax传过来的 data for (var i = 0; i < obj.length; i++) {//遍历数据 v ...

  10. excel 转换日期

    早上一朋友问我excel中如何将类似这样“19850421”的文本日期转换为“1985-04-21”.我的第一反应就是直接设置单元格格式为日期,于是打开excel试了试结果显示“########### ...