Java JVM如何启动超类和子类中的字段?
任何人都能说出为什么下面代码的输出是“null”吗?构造复杂对象并将细节委托给其子类的最佳方法是什么Java JVM如何启动超类和子类中的字段?,java,jvm,jls,Java,Jvm,Jls,任何人都能说出为什么下面代码的输出是“null”吗?构造复杂对象并将细节委托给其子类的最佳方法是什么 package com.test; public class ClassA { ClassA() { initHeader(); initBody(); initFooter(); } void initHeader() {} void initBody() {} void initFooter(
package com.test;
public class ClassA {
ClassA() {
initHeader();
initBody();
initFooter();
}
void initHeader() {}
void initBody() {}
void initFooter() {}
public static void main(String[] args) {
ClassB a = new ClassB();
System.out.println(a.obj);
}
}
class ClassB extends ClassA {
public Object obj = null;
ClassB() {
super();
}
void initHeader() {
obj = new Object();
}
}
首先,初始化
ClassA
的字段
然后调用ClassA
的构造函数,调用ClassB.initHeader()
然后,初始化
ClassB
的字段,覆盖initHeader()
所做的操作。此代码不从ClassB调用initHeader
,这是不正确的。
您可以通过向这两个类的initHeader
方法添加调试输出来验证它
public Object obj=null代码>包含两部分:
声明public Object obj
执行obj=null
构造函数运行时已知的第一部分(此时obj默认初始化为null
)
第二部分在构造函数之后执行,因此在initHeader之后执行,并覆盖obj
尝试只替换公共对象obj=null代码>通过公共对象obj代码>有趣的是,有人否决了唯一正确的答案(几乎是:调用了ClassB的构造函数,但因为它调用了super,所以也调用了ClassA的构造函数)!如果怀疑调试器是你的朋友-这正是正在发生的事情。由于我的upvote,投票结果现在是0。@mantrid我确信在编写一个漂亮(可读)的答案帮助方面做了一些努力。那么,构建复杂对象以避免这种混乱的最佳实践是什么呢?@AaronMao您所做的大部分都是好的,即使我个人尽可能限制复杂初始化的使用(或函数)使用多个层次结构级别。只需将公共对象obj=null;
更改为公共对象obj;
(正如xvorsx建议的那样)即可解决此问题@AaronMao:有一条一般规则:避免从构造函数调用非私有/非最终方法。构造复杂对象的最佳方法是什么…?-->保持简单实际上,第二部分在超级构造函数之后执行,然后子类构造函数执行。