efritz
efritz

Reputation: 5203

Java Constructor and Field Initialization Order

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.

Upvotes: 9

Views: 8839

Answers (4)

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340743

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 and are marking this as a potential bug.

See also

Upvotes: 16

Chandaneswar
Chandaneswar

Reputation: 1

The order of invoking the constructors of Parent-Sub class in case of inheritance is that, the constructor of Parent class always gets invoke first and then the constructor of Child class.

The Sub class calls the constructor of the base class by default using the Super(), if explicitly not given.

Upvotes: 0

Charlie Martin
Charlie Martin

Reputation: 112366

Depth first, a pre-order walk.

Anders makes a good point: Java only initializes fields that are native types implicitly. Any Object field is merely a reference to Object, and so it in fact initialized, but it's initialized to null.

Upvotes: 3

andersoj
andersoj

Reputation: 22884

Object fields are not implicitly initialized... you need to do the init. Maybe you need a lazy init in this case? Generally unpleasant to have the constructor calling methods that do non-trivial work, it's usually a smell that something is more complex than it wants to be.

Upvotes: 4

Related Questions