Java 构造函数和字段初始化顺序

标签 java inheritance initialization

我知道 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 工具,如 将此标记为潜在错误。

另见

关于Java 构造函数和字段初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10589828/

相关文章:

java - Java 逻辑短路运算符如何工作

swift - 具有许多属性的初始化类

java - Java套接字,创建自己的通用方法//恶性循环

c++ - 在堆栈与堆中没有构造函数的结构/类的初始化

scala - 在 Scala 中强制实现工厂的简洁方法

java - Hibernate 违反 UNIQUE KEY 约束

java - 编译器优化掉添加到序列化类的最终字段

C++ 继承 : confused with base member access from derived object

java - 找不到codingbat数组挑战的解决方案

java - Java 中的动态转换