以下内容来自周志明的《深入理解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. Fair Scheduler中的Delay Schedule分析

    延迟调度的主要目的是提高数据本地性(data locality),减少数据在网络中的传输.对于那些输入数据不在本地的MapTask,调度器将会延迟调度他们,而把slot分配给那些具备本地性的MapTa ...

  2. JavaScript 开发的45个经典技巧

    JavaScript是一个绝冠全球的编程语言,可用于Web开发.移动应用开发(PhoneGap.Appcelerator).服务器端开发(Node.js和Wakanda)等等.JavaScript还是 ...

  3. FTP Proxy Server

    本文将在Linux环境下实现一个简单的FTP代理服务器,主要内容涉及FTP主动/被动模式和简单的Socket编程. 1. 主动模式和被动模式 FTP有两种模式,即主动模式(Active Mode)和被 ...

  4. php 的txt操作,加入类容

    <?php $fr=fopen("./data/test.txt",'a'); //fopen(位置,打开方式) if(!$fr) { echo " error&q ...

  5. 嵌入式 python异常except语句用法与引发异常 zz

    http://blog.sina.com.cn/s/blog_8795b0970101dj0a.html

  6. Tyvj 题目1463 智商问题(分块)

    P1463 智商问题 时间: 1500ms / 空间: 131072KiB / Java类名: Main 背景 各种数据结构帝~各种小姊妹帝~各种一遍AC帝~ 来吧! 描述 某个同学又有很多小姊妹了他 ...

  7. PhantomJS linux系统下安装步骤及使用方法(网页截屏功能)

    PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, CSS 选择器, JSON, ...

  8. String类型和基本数据类型之间的转换

    Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...

  9. 史上最简单的socket

    1. client import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import ja ...

  10. go 准备

    坚持每天抽点时间 学习联系 go 语法 主要参考 https://tour.golang.org 官方导向,英语不好的可以切换到中文版本.这个之前都是墙外面的,只能访问国内映像地址 吐槽一下就是 里面 ...