Abstract class with final uninitialized field
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
}
}
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
}
}
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);
}
}
Instantiate the objects in the abstract class constructor and just pass the difference to the that constructor.