美国上市公司,专注Java培训22年

携程 Java 工程师的一道面向对象面试题


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();
   }
}

求这段程序的输出。

未老莫还乡 的评论:


【不要在构造器里调用可能被重载的虚方法,这是极度危险的】。构造器的初始化顺序大概是 父类静态块 子类静态块 父类初始化语句 父类构造函器 子类初始化语句 子类构造器。父类构造器执行的时候,调用了子类的重载方法,然而子类的类字段还在刚初始化的阶段,刚完成内存布局,只能输出null。

ihuning 的精华评论:

看我大师归来:

1. Base b = new Sub();

2. Base b = 直接忽略,从 new Sub();开始

3. 类加载器加载 Base,Sub 类到jvm;

4. 为Base,Sub 类中的两个属性baseName 分配存储空间,但是不初始化;

注意:属性的初始化时放在构造器中,按照代码顺序执行的。

5. new Sub会调用Sub的无参构造器,而在这个构造器中会隐式调用父类Base的无参构造器;

6. 父类Base的构造器中代码本质是

public Base()

{

baseName = "base";

callName();

}

即父类的属性baseName 的值为base。但为何输出null,骚年别急。

7. 因为父类构造器方法是在子类中调用的,即大环境是子类。此时,调用的方法callName()当然是指子类的方法。而这个方法打印的属性baseName当然也是子类的。那现在子类的属性baseName的值是多少呢?答案是null.因为此时子类Sub的构造器内代码本质是:

super();

baseName="sub";

此时baseName="sub"还没执行。

因此,左后的值当然是null.



【免责声明】本文部分系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,如涉及作品内容、版权和其它问题,请在30日内与我们联系,我们会予以重改或删除相关文章,以保证您的权益!

Java开发高端课程免费试学

大咖讲师+项目实战全面提升你的职场竞争力

  • 海量实战教程
  • 1V1答疑解惑
  • 行业动态分析
  • 大神学习路径图

相关推荐

更多

Java开班时间

收起