zoukankan      html  css  js  c++  java
  • [读书笔记]Java之动态分派

    以下内容来自周志明的《深入理解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类里的。

  • 相关阅读:
    jsp用equals判断两个字符串变量是否相等
    使用session在jsp页面之间传递多维数组,用于实现全局变量的效果
    C++实现对MySQL数据库的连接,以及增删改查
    VS2017项目中使用代码连接MySQL数据库,以及进行数据添加
    VS2017中遇到不存在从string到const char*的转换函数的解决方法
    windows系统转linux系统后磁盘的处理
    redis集群节点重启后恢复
    Jenkins 与Docker/Kubernetes的自动化CI流水(笔记)
    shell的运用 : jenkins 编译 打包前端发布 生产(tomcat)
    云服务器linux系统修改时间和时区
  • 原文地址:https://www.cnblogs.com/yasire/p/5426378.html
Copyright © 2011-2022 走看看