Java 构造函数和字段初始化顺序
我知道 Java 对象构造函数会隐式初始化其实例的非静态字段.但是,我不确定这在类层次结构中发生的顺序.例如:
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));
}
}
父类的构造函数调用子类中的一个方法,该方法抛出一个异常作为List
当前为空.
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.
我可以定义一个子构造函数并调用 super(),但这必须是构造函数主体中的第一行(这意味着我仍然没有机会在 getNextPiece
之前初始化 bag调用).
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.
推荐答案
没错.super()
,即使你没有显式添加它,也隐含地放置在每个构造函数中.这意味着首先调用 ShufflePieceSequence
的构造函数,但它所做的正是调用 AbstractPieceSequence
.
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
.
在 AbstractPieceSequence
中,您正在调用 ShufflePieceSequence
中定义的方法 - 该方法尚未初始化.事实上,您所做的实际上是一个非常微妙的错误.你永远不应该从构造函数中调用可覆盖的(包括 abstract
方法).时期.AFAIR 工具,例如 pmd 和 findbugs 将此标记为潜在错误.
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.
- 构造函数中的可覆盖方法调用有什么问题?
- 从构造函数调用非最终方法时要小心
- 确保构造函数不调用可覆盖的方法
相关文章