目录
一、动态分派调用
1.1、方法动态分派调用演示
- 一、动态分派调用
- 1.1、方法动态分派调用演示
- 1.2、方法动态分派调用的原因
-
示例代码
/** * @description: 动态分配调用示例 * @author: xz */ public class Test4 { static class Parent{ public void hello(){ System.out.println("hello parent"); } } static class Child1 extends Parent{ @Override public void hello() { System.out.println("hello Child1"); } } static class Child2 extends Parent{ @Override public void hello() { System.out.println("hello Child2"); } } public static void main(String[] args) { Parent p1 = new Child1(); Parent p2 = new Child2(); p1.hello(); p2.hello(); } }
-
输出结果
-
总结 显然这里不可能再根据静态类型来决定,因为静态类型同样都是Parent的两个变量p1和p2在调用hello()方法时执行了不同的行为,并且变量p1在两次调用中执行了不同的方法。
-
使用javap命令输出这段代码的字节码,尝试从中寻找答案。
-
原因就需要从invokevirtual指令的多态查找过程开始说起,invokevirtual指令的运行时解析过程大致分为以下几个步骤: (1)、找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C。 (2)、如果在类型C中找到与常量中的描述符合简单名称都相符的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束;如果不通过,则返回java.lang.IllegalAccessError异常。 (3)、否则,按照继承关系从下往上一次对C的各个父类进行第(2)步的搜索和验证过程。 (4)、如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError异常。