• 静态分派与动态分派——记一次被腾讯面试官暴虐的面试经历


    在腾讯的面试中被问到了重载的运行时多态是怎么实现的,显然这一块是我的知识盲区,所以赶紧补充下。

    静态分派

    依赖静态类型来定位方法执行版本的分派动作称作静态分派,静态分派的典型是方法重载。如下代码实例:

    public class StaticDispatch {
        static abstract class Human {
        }
    
        static class Man extends Human {
        }
    
        static class Woman extends Human {
        }
    
        public void sayHello (Human guy) {
            System.out.println("hello,guy");
        }
    
        public void sayHello (Man guy) {
            System.out.println("hello,gentleman");
        }
    
        public void sayHello (Woman guy) {
            System.out.println("hello,lady");
        }
    
        public static void main(String[] args) {
            Human man = new Man();
            Human woman = new Woman();
            StaticDispatch sr = new StaticDispatch();
            sr.sayHello(man);//hello,guy!
            sr.sayHello(woman);//hello,guy!
        }
    }
    

    对于这段代码的运行结果想必大家都很清楚,究其原因,重载的方法调用是由静态类型而非实际类型决定的,在编译器便决定了使用哪个重载版本,并会把这个方法的符号引用写到main()方法的两条invokevirtual指令的参数中。
    总结:Java重载是基于静态分派完成的。

    动态分派

    我们知道Java多态性另一种实现方式是“重写”,而这种运行时多态编译器是不可能知道它的实际调用的实例的,如下代码所示:

    Scanner in = new Scanner(System.in);
    Person person = null;
    if (in.nextLine().equals("chinese")) {
        person = new Chinese();
    } else {
        person = new English();
    }
    person.sayHello();
    

    在重载的场景下,JVM使用的是动态分派,即在运行时确定接受者的实际类型。JVM会在操作数栈中找到指向对象的实际类型,之后在该类的方法表(存在方法区中,存放着各个方法的实际入口)中找到对应描述符和和简单名称都相符的方法,同时进行访问权限校验,如通过则查找过程结束。如果没有找到匹配的方法,则通过继承关系在该类的父类的方法表中查找,查找到则结束,否则抛异常。

    参考资料

    多态在 Java 和 C++ 编程语言中的实现比较
    《深入理解Java虚拟机》

  • 相关阅读:
    杂记
    asp.net preview 5 bug[转]
    jquery笔记
    北京互联网创业团队诚邀英才加盟
    伊瓜苏大瀑布
    log4net udp组件的应用
    Mock介绍
    自写的BackgroundWorker的学习例子
    RegexBuddy使用例子,及Visual Studio中正则使用的请教
    TestDriven.NET2.14.2190(not RTM) last update at 2008723
  • 原文地址:https://www.cnblogs.com/wunsiang/p/13795782.html
Copyright © 2020-2023  润新知