• [读书笔记]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类里的。

  • 相关阅读:
    【转载】我的七个建议Joel Spolsky
    C语言文件读写操作
    【转】RO段、RW段和ZI段 Image$$??$$Limit 含义(zz)
    给大家一个测试webservice的软件
    .net 实现深拷贝的方法
    第一次设计数据访问层,大家给你建议,谢谢
    重新写博客
    (转)理解 Thread.Sleep 函数
    slk解压缩
    SMTP Service设置
  • 原文地址:https://www.cnblogs.com/yasire/p/5426378.html
Copyright © 2020-2023  润新知