Java 为什么';我的字段是否初始化为我给它的值

Java 为什么';我的字段是否初始化为我给它的值,java,Java,我有以下课程: public abstract class AClass { public AClass() { aMethod(); } abstract protected void aMethod(); } public class SubClass extends AClass { private int x = 5; private static final int y = 6; @Override p

我有以下课程:

public abstract class AClass {

    public AClass() {
        aMethod();
    }

    abstract protected void aMethod();

}

public class SubClass extends AClass {

    private int x = 5;
    private static final int y = 6;

    @Override
    protected void aMethod() {
        System.out.println("x: " + x + " | y: " + y);
    }

}

public class Main {

    public static void main(String[] args) {
        new SubClass();
    }

}
运行Main打印以下内容:x:0 | y:6


为什么要为x打印0?

因为当您创建
子类的实例时,它会调用其超类
AClass
的构造函数,此时,
x
尚未设置,这就是为什么它会获得默认值0的原因。

初始化顺序
aMethod()
在行
private int x=5之前调用


使用类似这样的代码示例是了解执行顺序的一种很好的方法。尝试添加静态和非静态初始化块。

初始化类后(加载后),静态字段立即初始化。现在当你打电话时
newsubclass()
发生以下情况

  • 子类
    的构造函数被称为
    子类
    的第一条语句(隐式)
  • 调用了
    超类的构造函数。-->您正在此处检查
    x
    的值
  • 一旦
    超类
    构造函数的执行完成,则初始化
    子类
    的实例级字段。因此,
    x
    将在此处初始化

  • 错误行为的原因是错误的初始化顺序:

  • newsubclass()
    执行
    AClass
    构造函数
  • AClass
    构造函数调用
    aMethod()
  • aMethod()
  • 子类
    初始化其非静态字段,使
    x
    变为
    5

  • 为了避免意外,永远不要在构造函数中调用虚拟方法(特别是重写方法)

    结果是,在初始化成员之前调用了超类构造函数

    private static final int y = 6;
    
    在您的情况下,执行以下顺序:

    • 调用构造函数
      子类
    • 立即调用构造函数
      AClass
    • 方法调用
      aMethod()
    • 初始化
      子类的成员
    这也是为什么不应从构造函数调用任何可重写方法的原因,因为被调用的方法可能访问未完全初始化的对象的状态

    private static final int y = 6;
    
    当构造函数调用aMethod()时,y的值为6,因为它是静态的,并且在类加载时初始化

    private int x = 5;
    
    而此初始化附加在构造函数主体的末尾。这意味着在执行aMethod时,变量x仍然具有默认值,即0

    子类的默认构造函数如下所示

    SubClass() {
        super();
        //All instance initialization are performed here.
    }
    

    我猜在初始化子类的私有成员x之前,会调用基类构造函数。(我的Java有点生疏了)但是所有的方法在Java中都是虚拟的,不是吗?但是,并非所有方法都是可重写的。@安德鲁·斯宾塞:是的,默认情况下Java方法是虚拟的(您可以声明非虚拟的
    final
    方法),如果您对虚拟性采用纯技术定义,甚至
    final
    Java方法也是虚拟的(它们是后期绑定的,忽略了优化)。但我更喜欢你的思考方式——毕竟,重要的是“最终”结果,即无法覆盖。