I aware that Java object constructors implicitly initialize their instance’s non-static fields. However, I’m unsure of the order that this happens in a class hierarchy. For example:
abstract public class AbstractPieceSequence implements PieceSequence
{
private Tetromino current;
private Tetromino preview;
public AbstractPieceSequence()
{
advance();
}
@Override
public final void advance()
{
if (preview == null) {
current = getNextPiece();
preview = getNextPiece();
} else {
current = preview;
preview = getNextPiece();
}
}
abstract protected Tetromino getNextPiece();
}
public class ShufflePieceSequence extends AbstractPieceSequence
{
private List<Shape> bag = new LinkedList<Shape>();
@Override
protected Tetromino getNextPiece()
{
if (bag.size() == 0) {
Collections.addAll(bag, Shape.I, Shape.J, Shape.L, Shape.O, Shape.S, Shape.T, Shape.Z);
}
return Tetromino.tetrominoes.get(bag.remove(0));
}
}
The parent’s constructor calls a method in the child class, which throws an exception as the value of List<Shape> bag is currently null.
I can define a child constructor and call super(), but that must be the first line in the constructor body (which means I still don’t have a chance to initialize bag before getNextPiece is called).
I am missing something obvious.
That’s right.
super(), even if you don’t add it explicitly, is placed implictly in every constructor. This means that the constructor ofShufflePieceSequenceis called first, but the very first thing it does is callingAbstractPieceSequence.In
AbstractPieceSequenceyou are calling a method defined inShufflePieceSequence– which has not been initialized. In fact what you are doing is actually a very subtle bug. You should never call overridable (includingabstractmethods) from constructor. Period. AFAIR tools like pmd and findbugs are marking this as a potential bug.See also