Java Constructor and Field Initialization Order

inheritance, initialization, java

Solution

That's right. `super()`, even if you don't add it explicitly, is placed implictly in every constructor. This means that the constructor of `ShufflePieceSequence` is called first, but the very first thing it does is calling `AbstractPieceSequence`.

In `AbstractPieceSequence` you are calling a method defined in `ShufflePieceSequence` - which has not been initialized. In fact what you are doing is actually a very subtle bug. You should never call overridable (including `abstract` methods) from constructor. Period. AFAIR tools like pmd and findbugs are marking this as a potential bug.

See also

- What's wrong with overridable method calls in constructors?

- Use Care When Calling Non-final Methods from Constructors

- Ensure that constructors do not call overridable methods

Problem

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.

Original source

Related problems