为什么我的字段没有初始化为我给它的值

时间:2014-09-12 09:39:30

标签: 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
    protected void aMethod() {
        System.out.println("x: " + x + " | y: " + y);
    }

}

public class Main {

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

}

Running Main打印以下内容:x:0 | y:6

为什么0会打印x?

6 个答案:

答案 0 :(得分:10)

错误行为的原因是错误的初始化序列

  1. new SubClass()执行AClass构造函数
  2. AClass构造函数调用aMethod()
  3. aMethod()显示x(目前为0)和y,因为静态6
  4. SubClass初始化其非静态字段,因此x变为5
  5. 为避免惊慌失措,从不在构造函数中调用虚拟方法(尤其是覆盖

答案 1 :(得分:4)

一旦初始化类(加载后),就会初始化静态字段。现在当你打电话给 new SubClass()发生以下事情。

  
      
  1. SubClass的构造函数被称为SubClass的第一个语句(隐式)
  2.   
  3. 调用SuperClass的构造函数。 - >您正在检查x此处
  4. 的值   
  5. SuperClass构造函数执行完成后,初始化SubClass的实例级字段。因此,x将在此初始化。
  6.   

答案 2 :(得分:3)

初始化顺序。在aMethod()

之前调用private int x = 5

使用像这样的代码示例来学习执行事物的顺序是很好的方法。尝试添加静态和非静态初始化块。

答案 3 :(得分:3)

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

在您的情况下,执行以下序列:

  • 致电建设者SubClass
  • 立即调用构造函数AClass
  • 调用方法aMethod()
  • 初始化SubClass
  • 的成员

这也是你不应该从构造函数中调用任何可重写方法的原因,因为被调用的方法可以访问未完全初始化的对象的状态。

答案 4 :(得分:1)

private static final int y = 6;

当构造函数调用 aMethod()时,y的值为6,因为它是静态的并且在类加载时被初始化。

private int x = 5;

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

SubClass 的默认构造函数看起来像

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

答案 5 :(得分:0)

因为当您创建Subclass的实例时,它会调用其超类AClass的构造函数,此时,x尚未设置为什么它会获取默认值值为0.