构造函数代码在Java中运行之前是否已初始化字段?

任何人都可以解释下面的程序的输出? 我认为构造函数是在实例variables之前初始化的。 所以我期待的输出是“XZYY”。

class X { Y b = new Y(); X() { System.out.print("X"); } } class Y { Y() { System.out.print("Y"); } } public class Z extends X { Y y = new Y(); Z() { System.out.print("Z"); } public static void main(String[] args) { new Z(); } } 

正确的初始化顺序是:

  1. 静态variables初始化程序和静态初始化块,如果该类尚未初始化,则按文本顺序排列。
  2. 在构造函数中的super()调用,无论是显式的还是隐式的。
  3. 实例variables初始化程序和实例初始化块,按照文本顺序。
  4. super()之后剩余的构造函数体。

请参阅Java虚拟机规范的§2.17.5-6部分。

如果您查看类文件的反编译版本

 class X { Y b; X() { b = new Y(); System.out.print("X"); } } class Y { Y() { System.out.print("Y"); } } public class Z extends X { Y y; Z() { y = new Y(); System.out.print("Z"); } public static void main(String args[]) { new Z(); } } 

你可以发现实例variablesy在构造函数内部移动,所以执行顺序如下

  1. 调用Z的构造函数
  2. 它触发X的默认构造函数
  3. X构造函数new Y()第一行被调用。
  4. 打印Y
  5. 打印X
  6. 调用构造函数Z new Y()的第一行
  7. 打印Y
  8. 打印Z

所有的实例variables都使用构造函数语句进行初始化。

初始化的顺序如下所示:

  1. 静态variables和初始化块按照它们出现的顺序
  2. 在构造函数体中调用super()
  3. 实例variables和初始化块,按照它们出现的顺序
  4. 其余的构造函数体

从Java虚拟机规范中的§12.5节开始 。

初始化序列在JLS 12.5中指定:

首先,内存分配给新的对象

2.然后,对象中的所有实例variables(包括在这个类及其所有超类中定义的variables)被初始化为它们的默认值

最后,调用构造函数。

https://stackoverflow.com/questions/26552799/which-run-first-default-values-for-instance-variables-or-super-constructors