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

编程入门 行业动态 更新时间:2024-10-07 06:42:11

不要在构造器里调用可能被重载的虚方法,<a href=https://www.elefans.com/category/jswz/34/1770804.html style=这是极度危险的"/>

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

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

publicclassBase

{

privateStringbaseName = "base";

publicBase()

{

callName();

}

publicvoidcallName()

{

System.out.println(baseName);

}

staticclassSubextendsBase

{

privateStringbaseName = "sub";

publicvoidcallName()

{

System.out.println(baseName);

}

}

publicstaticvoidmain(String[]args)

{

Baseb = newSub();

}

}


求这段程序的输出。


来自未老莫还乡 的评论:


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


更多推荐

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

本文发布于:2024-02-06 14:53:06,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1749693.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:这是   危险   方法   器里   不要在

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!