我一定花了一个多小时试图找出出现意外行为的原因.我最终意识到没有像我期望的那样设置场地.在耸耸肩并继续前进之前,我想明白为什么会这样.
在运行下面的示例时,我希望输出为true,但它是错误的.其他测试表明,我总是得到任何类型的默认值.
public class ClassOne {
public ClassOne(){
fireMethod();
}
protected void fireMethod(){
}
}
public class ClassTwo extends ClassOne {
boolean bool = true;
public ClassTwo() {
super();
}
@Override
protected void fireMethod(){
System.out.println("bool="+bool);
}
public static void main(String[] args) {
new ClassTwo();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
bool=false
Run Code Online (Sandbox Code Playgroud)
boolean bool = true;
public ClassTwo() {
super();
}
Run Code Online (Sandbox Code Playgroud)
是完全相同的
boolean bool;
public ClassTwo() {
super();
bool = true;
}
Run Code Online (Sandbox Code Playgroud)
编译器自动在构造函数中移动字段初始化(在超级构造函数调用之后,隐式或显式).
由于布尔字段默认值是false,当super()被称为(因此ClassOne()和fireMethod()),bool还没有被设置为true呢.
有趣的事实:以下构造函数
public ClassTwo() {
super();
fireMethod();
}
Run Code Online (Sandbox Code Playgroud)
将被理解为
public ClassTwo() {
super();
bool = true;
fireMethod();
}
Run Code Online (Sandbox Code Playgroud)
由JVM,因此输出将是
bool=false
bool=true
Run Code Online (Sandbox Code Playgroud)
在子类构造函数之前调用超类构造函数.在Java中,在运行构造函数之前,所有实例成员都有其默认值(false,0,null).因此,当super()被调用时,bool仍然是假的(布尔值的默认值).
更一般地说,从构造函数(在ClassOne中)调用可覆盖的方法是一个坏主意,因为您刚刚发现:您最终可能还在处理尚未完全初始化的对象.