对于类继承的情况,我发现了以下对象初始化顺序:
- 父类的静态字段;
- 父类的静态初始化块;
- Child 类的静态字段;
- Child类的静态初始化块;
- 父类的非静态字段;
- 父类的非静态初始化块;
- 父类构造函数;
- Child 类的非静态字段;
- 类 Child 的非静态初始化块
- 子类构造函数。
但是,如果父项和子项中都有多个构造函数怎么办——它们是如何加载的?parent 的所有构造函数,然后是 successor,还是按书写顺序一次一个?
在面试中,有人向我展示了一个示例,说明继承人的构造函数(或其执行 - 我记不清了)可能由于父母构造函数的顺序而出现错误,但我无法在任何地方找到明确的信息并且代码中这种情况的示例。你能澄清这一点吗?
在派生类中,调用父类的一个构造函数。
要么在子构造函数的开头使用 construct 显式调用父构造函数,要么在编译器在构造函数的开头
super替换它时隐式调用它。super();而且,如果父类没有不带参数的构造函数,那么代码会导致编译错误。有关此的文档。
因此,对于有多少父构造函数以及哪些在子构造函数中被调用是没有不确定性的。
正如@zRrr 所写,如果在父构造函数中调用重写或子实现的方法,而父构造函数又使用尚未初始化的子字段,那么调用构造函数的顺序和类字段的初始化可能会出现问题。
例子:
它会显示在屏幕上
Animal null,因为在调用该方法的那一刻,getNameyDog字段thisName还没有被初始化。创建
animal时,默认构造函数 y 被调用Dog,这首先导致调用不带参数的构造函数 yAnimal,然后才初始化该字段thisName。这篇文章还有另一个例子:
屏幕将显示:
但是,如果您替换
String lowerString = null;为String lowerString;,则输出将是:原始版本的问题是对的赋值
null发生String lowerString = null;在调用父类的构造函数之后,而父类的构造函数又调用Initializer.initialize. 也就是说,lowerString首先写的是"lowerInited",然后是null。这两个示例都说明了由于对代码执行顺序的错误假设而引起的问题。很难理解这段代码中执行的是什么,这本身就表明在实践中不应该这样写代码。
我认为这是顺序: