# 首先Java 为什么会有这2中分派

        因为 . java文件在编译期间并不包括传统编过程中的连接环节,所以在生成的 .class文件中有关一切方法调用的信息都是用符号引用表示,并没有方法在实际运行是在内存中的入口地址。这一特性让Java有了强大的动态扩充能力,但也因此方法调用变得复杂,需要在类加载期间,甚至到运行期间才能确定目标方法的直接引用。(方法调用并不等于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程)。而根据确定调用那个方法的时期可以将方法调用分为静态分派和动态分派。

# 静态分派

在编译期间,可以根据变量的静态类型确定方法执行版本的分派动作称作静态分派。典型的是方法的重载。

# 动态分派

在编译期间确定不下来,只有在方法调用时,根据对象的实际类型确定方法执行版本的分派动作称作动态分派。 重写。

#Java虚拟机是如何根据实际类型来分派方法执行版本的呢?

            我们从invokevirtual指令的多态查找过程开始说起,invokevirtual指令的运行时解析过程大致分为以下几个步骤:
            1、找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C。
            2、如果在类型C中找到与常量中的描述符和简单名称相符合的方法,然后进行访问权限验证,如果验证通过则返回这个       方法的直接引用,查找过程结束;如果验证不通过,则抛出java.lang.IllegalAccessError异常。
            3、否则未找到,就按照继承关系从下往上依次对类型C的各个父类进行第2步的搜索和验证过程。
            4、如果始终没有找到合适的方法,则跑出java.lang.AbstractMethodError异常。

            由于invokevirtual指令执行的第一步就是在运行期确定接收者的实际类型,所以两次调用中的invokevirtual指令把常量池中的类方法符号引用解析到了不同的直接引用上,这个过程就是Java语言方法重写的本质。