gpt4 book ai didi

java - 通过声明初始化类 DS 字段 - 在构造函数调用之前还是之后?

转载 作者:行者123 更新时间:2023-12-02 11:35:45 25 4
gpt4 key购买 nike

在处理公司的遗留代码时,我在运行时遇到了 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() {
.....
}
}

在从 ConcreteClass 调用 super 和从 PreConcreteClass 调用 super 后,调用 ConcreteClass 的重写更新方法时,会引发 NPE。原因是internalDS - 它为空,导致for循环抛出NPE。

首先 - 这与我一直期望的相反 - 在声明时初始化的类字段在执行构造函数的范围之前初始化。通过 super 调用派生类的构造函数时不是这样吗?

第二 - 我通过添加一个由 AbstractClass 构造函数调用的 init 方法解决了 NPE,该方法由 AbstractClass 给出了一个空实现,并被 ConcreteClass 通过内部 DS 上的初始化覆盖。

我查阅了一些一般建议in stack overflow 。我在工作中与同事进行了一些讨论,我们一致认为上述设计存在继承问题,导致了 NPE。由于这是我们不想彻底更改的遗留代码,因此我想知道是否有人有更好的替代方案来替代我使用的 init 方法解决方案。注意 - 每个类都有多个构造函数。

最佳答案

不,编译器在调用 super 之后移动构造函数中的那些初始值设定项,因此您的代码等效于:

public class ConcreteClass extends PreConcreteClass{
private List<Object> internalDS;
public ConcreteClass() {
super();
internalDS = new ArrayList<>();
...
}
@Override
protected void update() {
....
for(Object o : internalDS) {
...
}
...
}

请注意,有一条通用规则可以以更简洁的方式避免这种情况:永远不要在构造函数中调用非 final方法。它会把事情搞砸。

关于java - 通过声明初始化类 DS 字段 - 在构造函数调用之前还是之后?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48961601/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com