码迷,mamicode.com
首页 > 编程语言 > 详细

最近很火的携程Java 工程师的一道面向对象面试题

时间:2015-10-09 19:58:03      阅读:319      评论:0      收藏:0      [点我收藏+]

标签:

  最近这道面试题,传遍程序员各大小园地,本小白特摘抄整理与大家一起学习:

原题:

package com.gxlee;

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();
        System.out.println(b);
    }
}

求这段程序的输出。

解答此题关键在于理解和掌握类的加载过程以及子类继承父类后,重写方法的调用问题:

从程序的执行顺序去解答:

1、Base b = new Sub();

  声明父类变量b对子类的引用,JAVA类加载器将Base,Sub类加载到JVM;

2、JVM为Base,Sub 的的成员开辟内存空间

  此时,Base 和Sub类中的值为null;

3、new sub()

  调用构造函数,由于Sub类继承自Base而无自定义构造器,因此先调用父类Base的无参构造;

4、父类午餐构造的本质为:

  public Base(){

  baseName= "base";

  callName();

    }

  即将父类的baseName赋值为“base”,赋值后调用callName();

5、callName 在子类中被重写,因此调用子类的callName();

6、调用子类的callName,打印baseName

  此baseName为子类Sub的成员变量,而此时该成员尚未初始化,因此为Null;

7、实际上在new Sub()时,实际执行过程为:

  public Sub(){

      super();

   baseName = "sub"; 

    }

  可见,在baseName = "sub"执行前,子类的callName()已经执行,所以子类的baseName为默认值状态null;

总结:

未老莫还乡 的评论:

   【不要在构造器里调用可能被重载的虚方法,这是极度危险的】。

  构造器的初始化顺序大概是:父类静态块 ->子类静态块 ->父类初始化语句 ->父类构造函器 ->子类初始化语句 子类构造器。

   父类构造器执行的时候,调用了子类的重载方法,然而子类的类字段还在刚初始化的阶段,刚完成内存布局,只能输出null。

最近很火的携程Java 工程师的一道面向对象面试题

标签:

原文地址:http://www.cnblogs.com/Hfly/p/4864842.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!