tags:

views:

139

answers:

3

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
  }
}
+6  A: 

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
  }
}
Jon Skeet
+1 Beat me to it -- had the same answer going, with trivial differences (i.e. using an int parameter and calling super() instead of this()).
MCory
Thanks. Any specific reason why you made it private instead of protected? Say I want to access it directly in the subclasses. And why you use this() instead of super()?
Lieven
@MCory @Lieven I'm guessing this was a quick answer from a smartphone, where it's not easy to get everything right the first time.
Michael Myers
@lieven: The "this" was a typo - but I prefer fields to be private pretty much everywhere, and shouldn't be part of your exposed API - which includes what derived classes get to see.
Jon Skeet
From a bytecode/verifier perspective, `final` means only assigned by the class itself (can be unassigned, assigned multiples times, assigned by a method other than a constructor (not 100% sure about from other instances/static methods)).
Tom Hawtin - tackline
@Tom: That's very interesting. I wish Java allowed multiple assignments within the constructor... this has caused me to write some ugly code to work around it before now.
Jon Skeet
A: 

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)

Uri
Ooops, sorry. That was a copy/paste error. I've edited my code.
Lieven
+2  A: 

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

ctrlShiftBryan