我知道 Java 对象构造函数会隐式初始化其实例的非静态字段。但是,我不确定这在类层次结构中发生的顺序。例如:
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));
}
}
父类的构造函数调用子类中的方法,抛出异常为List<Shape> bag
的值|当前为空。
我可以定义一个子构造函数并调用 super(),但那必须是构造函数主体中的第一行(这意味着我仍然没有机会在调用 getNextPiece
之前初始化包)。
我遗漏了一些明显的东西。
最佳答案
没错。 super()
,即使您没有显式添加它,也会隐含地放置在每个构造函数中。这意味着首先调用 ShufflePieceSequence
的构造函数,但它做的第一件事是调用 AbstractPieceSequence
。
在 AbstractPieceSequence
中,您正在调用 ShufflePieceSequence
中定义的方法 - 该方法尚未初始化。事实上,您所做的实际上是一个非常微妙的错误。你永远不应该从构造函数中调用可重写的(包括 abstract
方法)。时期。 AFAIR 工具,如 pmd和 findbugs将此标记为潜在错误。
另见
关于Java 构造函数和字段初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10589828/