阿里巴巴难度系数五颗星的试题,小白竟然说很简单
阿里巴巴难度系数五颗星的试题,小白竟然说很简单
阿里巴巴难度系数五颗星的试题,小白竟然说很简单牛客网上有道阿里巴巴的面试题,网站显示该题难度系数五颗星
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、子类引用指向子类的对象,在涉及父类方法调用时,比如调用父类构造函数、父类代码块涉及重写函数等参照第一条,调用子类的方法