阿里巴巴难度系数五颗星的试题,小白竟然说很简单

牛客网上有道阿里巴巴的面试题,网站显示该题难度系数五颗星代码如下:public class Base{ private String baseName = "base"; public Base(){ callName(); } public void callName(){ System. out. println(baseName); } static class Sub extends Base{
摘要由CSDN通过智能技术生成

牛客网上有道阿里巴巴的面试题,网站显示该题难度系数五颗星

原题

在这里插入图片描述

代码如下:

public class Base
{
    private String baseName = "base";
    public Base(){
        callName();
    }

    public void callName(){
        System. out. println(baseName);
    }

    static class Sub extends Base{
        private String baseName = "sub";
        public void callName(){
            System. out. println (baseName) ;
        }
    }
    public static void main(String[] args){
        Base b = new Sub();
    }
}

咋一看,好像是考察类的加载顺序,应该会先加载Sub类,所以会输出sub
也有人表示不服,虽然会先从Sub类开始加载,但根据加载顺序,会先加载父类的构造函数
所以结果会输出base
——————————————————————————————————
但答案是null~
在这里插入图片描述

调试顺序

在这里插入图片描述

分析

我们知道一般的类加载顺序是:先静态变量,然后静态代码块,其次是成员变量和普通代码块,最后是构造函数

new Sub()先加载基类成员变量,baseName = "base",没问题

然后加载基类构造函数public Base(),,但是构造函数中调用了callName

关键就在这个callName,它在子类Sub中也存在

再仔细看一下main方法Base b = new Sub();

恰好满足多态的三个必要条件

1、 继承

2、 子类重写父类方法

3、 父类引用指向子类对象

所以在父类的构造函数中调用的callName实际会调用子类的callName,而此时子类中的成员变量baseName还未加载,没有被赋值,所以为null

此处 不仅仅考察了类的加载顺序,还考察了java多态的特性

ON java 8这本书中第九章给出了相关解释
在这里插入图片描述

在这里插入图片描述
后期绑定——多态
在这里插入图片描述

验证

也就是说,父类的引用指向子类的对象时,调用共有方法,会执行子类方法,改造一下验证

public class Base {
    private String baseName = "base";
    public Base() {
        callName();
    }

    public void baseMethod(){
        System. out. println("baseMethod");
    }

    public void commonMethod(){
        System. out. println("commonMethod for Base");
    }

    public void callName() {
        System. out. println("Base callName(): "+baseName);
    }

    static class Sub extends Base {
        private String baseName = "sub";

        public void subMethod(){
            System. out. println("subMethod");
        }

        public void commonMethod(){
            System. out. println("commonMethod for Sub");
        }

        public void callName() {

            System. out. println ("Sub callName(): "+baseName) ;
        }
    }
    public static void main(String[] args) {

        System. out. println("************父类引用指向子类的对象**************");
        Base baseWithSub = new Sub();
        baseWithSub.baseMethod();
        baseWithSub.commonMethod();

        System. out. println("***********父类引用指向自己的对象***************");

        Base base = new Base();// 
        base.baseMethod();
        base.commonMethod();

        System. out. println("##############子类引用指向子类的对象##################");
        
        Sub sub = new Sub();
        sub.subMethod();
        sub.commonMethod();

    }
}

结果
在这里插入图片描述

总结

总结一下就是
1、父类的引用指向子类的对象,通过父类的引用调用父类、子类中均有的方法,那么java会自动调用子类的方法
2、父类的引用指向父类的对象,调用的是自己的方法

3、子类引用指向子类的对象,在涉及父类方法调用时,比如调用父类构造函数、父类代码块涉及重写函数等参照第一条,调用子类的方法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值