类中的初始化顺序

时间:2013-04-28 10:59:39

标签: java class inheritance

为什么在构造函数被调用之前,类变量被初始化,如果有问题的类没有扩展任何其他类,但是构造函数首先被调用,而如果有问题的类正在扩展其他类,则完成类变量的初始化!

e.g。假设我有一个班级

public class Windows {
    public Windows() {
        System.out.println("in window");
    }
}

我有一个基类。

public class BaseClass {
    public BaseClass() {
        System.out.println("in base");
    }
}

最后我还有一节课。

public class ChildClass extends BaseClass {

Windows w = new Windows();

public ChildClass() {
    System.out.println("in subclass");

}

public static void main(String[] args) {
    System.out.println(new ChildClass());
}
}

将导致

  

在基地   在窗口中   在子类

这表明基类构造函数被调用,这意味着子类构造函数被调用,但是在基类构造函数完成之后,为什么字段被初始化了?即不应该像

那样
  

在基地   在子类中   在窗口

这将解释一些事情!

如果我这样做

public class ChildClass {

Windows w = new Windows();

public ChildClass() {
    System.out.println("in subclass");

}

public static void main(String[] args) {
    System.out.println(new ChildClass());
}
}

我会得到

  在窗口中

  在子类

表明在构造函数窗口字段初始化之前。困惑!?!?!?如果我添加一些静态字段,图片甚至会引起混淆!

一些解释是JVM首先初始化基类,然后是当前类的字段,最后是构造函数。这是真的吗?

一些解释会很棒!!

1 个答案:

答案 0 :(得分:4)

关于Java的最好的朋友是Java Language Specification。关于您的问题,您可以找到答案here

  

在对新创建的对象的引用之前返回为   结果,处理指示的构造函数以初始化new   使用以下过程对象:

     
      
  1. 将构造函数的参数分配给此构造函数调用的新创建的参数变量。
  2.   
  3. 如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7.1节)开头(使用此),则   评估参数并处理构造函数调用   递归地使用这五个相同的步骤。如果那个构造函数   调用突然完成,然后此过程突然完成   出于同样的原因;否则,继续执行第5步。
  4.   
  5. 此构造函数不以同一个类中的另一个构造函数的显式构造函数调用开头(使用此方法)。如果   这个构造函数用于Object以外的类,然后是这个   构造函数将以a的显式或隐式调用开始   超类构造函数(使用超级)。评估参数和   使用这些来递归地处理超类构造函数调用   同样的五个步骤。如果该构造函数调用突然完成,   然后由于同样的原因,这个程序突然完成。除此以外,   继续第4步。
  6.   
  7. 为此类执行实例初始值设定项和实例变量初始值设定项,分配实例变量的值   初始化器到相应的实例变量中   从左到右的顺序,它们在源代码中以文本形式出现   为了上课。如果执行任何这些初始化程序导致   异常,然后没有处理进一步的初始化程序   程序突然完成同样的异常。除此以外,   继续第5步。
  8.   
  9. 执行此构造函数的其余部分。如果该执行突然完成,则此过程突然完成   出于同样的原因。否则,此过程正常完成。
  10.