Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
658 views
in Technique[技术] by (71.8m points)

inheritance - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 very 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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...