通过声明初始化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() {
       .....
    }
}

在调用Concreteclass的Super和Prodonconconcreteclass的Super后,将NPE抛出。原因是内部的 - 无效,导致for循环扔出NPE。

首先 - 这违背了我一直期望的 - 在执行构造函数范围之前,先初始化了在声明中初始化的类字段。通过超级?

second-我通过添加一个INIT方法来解决NPE,该方法由AbstractClass构造器调用,该方法由AbstractClass赋予了空的实现,并被ConcreteClass覆盖,并在Internalds上进行了初始化。

我查找了堆栈溢出中的一些一般建议。我在工作中与同事进行了一些讨论,我们同意上面的设计有一个继承的问题,导致NPE。由于这是我们不想大幅更改的旧代码,因此我知道是否有人可以更好地替代我使用的Init方法解决方案。注意 - 每个类都有多个构造函数。

no,编译器在调用超级后正在构造函数中移动这些初始化器,因此您的代码等同于此:

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

请注意,有一个通用规则可以以更干净的方式避免这种情况:从不在构造函数中调用非最终方法。它会搞砸了。

最新更新