栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

父类构造函数调用子类重写函数

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

父类构造函数调用子类重写函数

先看下面这段代码,运行后会输出什么结果呢?

public class Polymorphic {
    static class Father{
        public int money = 1;

        public Father(){
            money = 2;
            show();
        }

        public void show() {
            System.out.println("father: $" + money);
        }
    }

    static class Son extends Father{
        public int money = 3;

        public Son() {
            money = 4;
            show();
        }
        
        public void show() {
            System.out.println("son: $" + money);
        }
    }

    public static void main(String[] args) {
        Father gay = new Son();
        System.out.println("gay: $" + gay.money);
    }
}

输出的结果为

son: $0
son: $4
gay: $2

两次都输出的是“son”,这是因为Son类在创建时会先调用父类的构造函数,父类构造函数中调用show(),实际执行的是子类重写的方法,子类show()方法中访问子类的money字段,这是money字段还未被初始化,值为0,字段不参与多态,最后gay访问的是父类的money。

从字节码的角度来看,父类构造函数中调用show()是一次虚方法调用,在Java中静态方法(invokestatic)、私有方法(invokespecial)、实例构造器(invokespecial)、父类方法(invokespecial)以及被final修饰的方法(invokevirtual),这5种方法统称为“非虚方法”,其他方法就称为“虚方法”,使用invokestatic和invokespecial指令调用的方法,在解析阶段就可确定唯一的调用版本,使用invokevirtual指令调用的方法,是在运行期确定方法接收者的实际类型,根据实际类型确定方法执行版本。

PS: final方法虽然是使用invokevirtual指令调用,但因为它无法被覆盖,没有其他版本的可能,所以不需要对方法接收者进行多态选择。

将Son类改成如下代码:

static class Son extends Father{
        public int money = 3;

        public Son() {
            money = 4;
            super.show();
            show();
        }

        public void show() {
            System.out.println("son: $" + money);
        }
    }

可看到字节码如下:

在子类中调用父类的show方法是用invokespecial指令调用,调用自身的普通方法是用invokevirtual指令调用。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/353617.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号