-1

如果所讨论的类没有扩展任何其他类,但是首先调用构造函数,并且如果所讨论的类正在扩展其他类,那么为什么要在调用构造函数之前初始化类变量!

例如,假设我有一堂课

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首先初始化基类的东西,然后是当前类的字段,最后是构造函数。这是真的吗?

一些解释会很棒!

4

1 回答 1

4

关于 Java,您最好的朋友是Java 语言规范。关于你的问题,你可以在这里找到答案:

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

  1. 将构造函数的参数分配给此构造函数调用的新创建的参数变量。
  2. 如果此构造函数以同一类中另一个构造函数的显式构造函数调用(第 8.8.7.1 节)开始(使用 this),则评估参数并使用这五个相同的步骤递归地处理该构造函数调用。如果该构造函数调用突然完成,则此过程出于相同原因而突然完成;否则,继续执行步骤 5。
  3. 此构造函数不以显式构造函数调用同一类中的另一个构造函数开始(使用 this)。如果此构造函数用于 Object 以外的类,则此构造函数将以显式或隐式调用超类构造函数(使用 super)开始。使用这五个相同的步骤递归地评估超类构造函数调用的参数和过程。如果该构造函数调用突然完成,则此过程出于相同的原因突然完成。否则,继续执行步骤 4。
  4. 执行该类的实例初始化程序和实例变量初始化程序,将实例变量初始化程序的值分配给相应的实例变量,按照它们在源代码中以文本形式出现的从左到右的顺序。如果执行这些初始化程序中的任何一个导致异常,则不会处理更多初始化程序,并且此过程会突然完成相同的异常。否则,继续执行步骤 5。
  5. 执行此构造函数的其余部分。如果该执行突然完成,则此过程出于同样的原因突然完成。否则,此过程正常完成。
于 2013-04-28T11:17:13.440 回答