博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jvm中的动态分派
阅读量:7123 次
发布时间:2019-06-28

本文共 809 字,大约阅读时间需要 2 分钟。

动态分派与复写密不可分,因为java中存在向上转型,这样就涉及到方法的调用问题。先看一下示例代码

package com.dy.xidian;class Test1 {    public void say() {        System.out.println("Test1");    }}public class Test extends Test1 {    public static void main(String[] args) {        Test1 t = new Test();        t.say();    }    public void say() {        System.out.println("Test");    }}

代码中创建了一个Test()对象,然后将其向上转型为Test1类型,然后调用say()方法。那么问题来了,调用的say()是父类的方法还是子类的方法。先看一下字节码文件

在字节码文件中,我们可以观察到在main()方法中创建了Test文件,然后调用构造器(<init>)方法,紧接着调用Test1.say()方法。那么最后应该输出的是Test1,但是运行上面的代码会发现输出的是Test。出现这种原因和invokevirtual指令有关。

invokevirtual指令执行过程

  • 找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C
  • 如果C中有对应的方法则直接返回该方法的直接引用(即C实现了改方法),否则按照继承关系从下往上依次对C的各个父类进行查找,如果没有查找到则抛出异常

所以上面代码中t是静态类型,编译时就可以确认,为Test1。而其对应的对象是实际类型,为Test。所以按照上面的步骤最后的结果输出的应该是Test。

 

转载于:https://www.cnblogs.com/xidongyu/p/5915522.html

你可能感兴趣的文章
Java总结篇系列:Java泛型
查看>>
SqlHelper
查看>>
html 标签总结
查看>>
《PyCon2018》系列二:Elegant Solutions For Everyday Python Problems
查看>>
还是编码 汉字(GB2312和GBK)的ASCII码对照表
查看>>
[译]C++书籍终极推荐
查看>>
读<程序设计语言原理>
查看>>
类加载
查看>>
特殊运算符
查看>>
MySQL FEDERATED 存储引擎的使用
查看>>
生日小助手的问答帮助——随时更新,长期有效……
查看>>
jQuery Deferred
查看>>
jQuery data
查看>>
c#操作MySQL数据库中文出现乱码(很多问号)的解决方法
查看>>
bzo1007 [HNOI2008]水平可见直线
查看>>
Rotate Image <leetcode>
查看>>
301
查看>>
HAL_RTC_MspInit Msp指代什么?
查看>>
I.MX6 默认打开 USB adb
查看>>
2018中国大学生程序设计竞赛 - 网络选拔赛 hdu Find Integer 数论
查看>>