java在构造函数调用之前或之后通过声明初始化类DS字段?
在处理我公司的遗留代码时,我在运行时遇到了一个NPE。 调试后,我遇到了以下情况:
public class ConcreteClass extends PreConcreteClass{
private List<Object> internalDS = new ArrayList<>();
public ConcreteClass() {
super();
....
}
@Override
protected void update() {
....
for(Object o : internalDS) {
...
}
...
}
public class PreConcreteClass extends AbstractClass{
......
public PreConcreteClass() {
super();
......
}
......
}
protected abstract class AbstractClass {
protected AbstractClass() {
.....
update();
....
}
protected void update() {
.....
}
}
NPE是在从ConcreteClass调用super和从PreConcreteClass调用super之后,在调用ConcreteClass的重写更新方法时抛出的。原因是internalDS——它为空,导致for循环抛出NPE
首先——这与我一直期望的相反——在声明时初始化的类字段在执行构造函数的作用域之前被初始化。当通过super调用派生类的构造函数时,不是这样吗
第二,我通过添加一个init方法解决了NPE问题,该方法由AbstractClass构造函数调用,AbstractClass为其提供了一个空的实现,并由ConcreteClass在internalDS上进行初始化来覆盖
我查阅了一些一般建议。 我在工作中与同事进行了一些讨论,我们一致认为上面的设计存在继承问题,导致了NPE。 由于这是我们不想大幅更改的遗留代码,我想知道是否有人能更好地替代我使用的init方法解决方案。 注意:每个类都有多个构造函数
# 1 楼答案
不,编译器会在调用super后移动构造函数中的初始值设定项,因此您的代码相当于:
请注意,有一条一般规则可以以更简洁的方式避免这种情况:从不在构造函数中调用非final方法。它会把事情搞砸的