Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 841
efritz Avatar asked May 14 '12 19:05

efritz


People also ask

Does order matter in constructor Java?

Yes it matters. In the example above, the first argument has to be an integer, and the second has to be a string. Constructors are chosen according to the rules in the language spec. TL;DR: yep, there have to be same number, and they've got to be in the same order.

What is the order of execution of constructors in Java?

Answer: Order of execution of constructors in inheritance relationship is from base /parent class to derived / child class. We know that when we create an object of a class then the constructors get called automatically.

In which order are instance variables initialized?

In Java, the order for initialization statements is as follows: static variables and static initializers in order. instance variables and instance initializers in order. constructors.

What is the order of execution in Java?

Order of execution When you have all the three in one class, the static blocks are executed first, followed by constructors and then the instance methods.


2 Answers

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 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
like image 171
Tomasz Nurkiewicz Avatar answered Sep 24 '22 18:09

Tomasz Nurkiewicz


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.

like image 26
andersoj Avatar answered Sep 21 '22 18:09

andersoj