Abstract class with final uninitialized field

JavaOop

Java Problem Overview


I was wondering if the below code makes any sense, since the compiler warns that "the blank final field objects may not have been initialized". Is there a better way of doing this?

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
  }
}

Java Solutions


Solution 1 - Java

I would make the field final and force the constructors to pass the value up:

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
  }
}

Solution 2 - Java

The problem with initializing the final parameters directly in the constructor of the sub-classes is that you need to do it all in one line since super() must be the first statement of the constructor. So instead, I prefer to make the constructor non-public and make a static build method like this:

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);
  }
}

Solution 3 - Java

Instantiate the objects in the abstract class constructor and just pass the difference to the that constructor.

Solution 4 - Java

Generally speaking, it might be better to have a constructor in the base class that always sets the field, and not have a default constructor that doesn't set it. The subclasses can then explicitly pass the parameter in the first line of their constructor using super(value)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCantillonView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaqwertzguyView Answer on Stackoverflow
Solution 3 - JavactrlShiftBryanView Answer on Stackoverflow
Solution 4 - JavaUriView Answer on Stackoverflow