【问题标题】:Abstract class with final uninitialized field具有最终未初始化字段的抽象类
【发布时间】:2014-12-04 04:59:22
【问题描述】:

我想知道下面的代码是否有意义,因为编译器警告说“空白的最终字段对象可能尚未初始化”。有更好的方法吗?

public abstract Test {
  protected final ArrayList<Object> objects;
}

public TestSubA extends Test {

  public TestSubA() {
    objects = new ArrayList<Objects>(20);
    // Other stuff
  }
}

public TestSubB extends Test {

  public TestSubB() {
    objects = new ArrayList<Objects>(100);
    // Other stuff
  }
}

【问题讨论】:

  • +1:因为有兴趣做正确的事。

标签: java oop


【解决方案1】:

我会将字段设为 final 并强制构造函数向上传递值:

public abstract class Test {
  private final ArrayList<Object> objects;

  protected ArrayList<Object> getObjects() {
    return objects;
  }

  protected Test(ArrayList<Object> objects) {
    this.objects = objects;
  }
}

public class TestSubA extends Test {

  public TestSubA() {
    super(new ArrayList<Object>(20));
    // Other stuff
  }
}

public class TestSubB extends Test {

  public TestSubB() {
    super(new ArrayList<Object>(100));
    // Other stuff
  }
}

【讨论】:

  • +1 打败我——答案相同,只是有一些细微的差别(即使用 int 参数并调用 super() 而不是 this())。
  • 谢谢。您将其设为私有而不是受保护的任何具体原因?假设我想直接在子类中访问它。以及为什么你使用 this() 而不是 super()?
  • @MCory @Lieven 我猜这是来自智能手机的快速回答,第一次就做好一切并不容易。
  • @lieven:“this”是一个错字——但我更喜欢几乎在任何地方都是私有的字段,并且不应该成为你公开的 API 的一部分——这包括派生类可以看到的内容。
  • 从字节码/验证器的角度来看,final 表示仅由类本身分配(可以未分配,多次分配,由构造函数以外的方法分配(不是 100% 确定来自其他实例/静态方法))。
【解决方案2】:

直接在子类的构造函数中初始化最终参数的问题是你需要在一行中完成所有这些,因为 super() 必须是构造函数的第一个语句。因此,我更喜欢将构造函数设为非公开,并创建一个像这样的静态构建方法:

public abstract class Test {
  protected final ArrayList<Object> objects;

  protected Test(ArrayList<Object> objects) {
    this.objects = objects;
  }
}

public class TestSubA extends Test {
  public static TestSubA build() {
    ArrayList<Object> objects = new ArrayList<Object>(20);
    objects.put(...);
    // Other stuff
    return new TestSubA(objects);
  }

  private TestSubA(ArrayList<Object> objects) {
    super(objects);
  }
}

【讨论】:

    【解决方案3】:

    在抽象类构造函数中实例化对象并将差异传递给该构造函数。

    【讨论】:

      【解决方案4】:

      一般来说,最好在基类中有一个始终设置字段的构造函数,而不是不设置它的默认构造函数。然后子类可以使用 super(value) 在其构造函数的第一行显式传递参数

      【讨论】:

      • 糟糕,抱歉。那是一个复制/粘贴错误。我已经编辑了我的代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      相关资源
      最近更新 更多