8

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が現在nullであるため、例外をスローします。

子コンストラクターを定義してsuper()を呼び出すことはできますが、これはコンストラクター本体の最初の行である必要があります(つまり、呼び出される前にbagを初期化する機会がまだありませんgetNextPiece)。

明らかな何かが欠けています。

4

4 に答える 4

15

それは正しい。super()、明示的に追加しなくても、すべてのコンストラクターに暗黙的に配置されます。これは、のコンストラクターがShufflePieceSequence最初に呼び出されることを意味しますが、それが行うのはまさにそれですAbstractPieceSequence

AbstractPieceSequenceで定義されたメソッドを呼び出していますが、これShufflePieceSequenceは初期化されていません。実際、あなたがしていることは実際には非常に微妙なバグです。コンストラクターからオーバーライド可能(abstractメソッドを含む)を呼び出さないでください。限目。などのAFAIRツールは、これを潜在的なバグとしてマークしています。

も参照してください

于 2012-05-14T19:34:59.000 に答える
4

オブジェクトフィールドは暗黙的に初期化されません...initを実行する必要があります。この場合、怠惰なinitが必要なのかもしれません。コンストラクターが重要な作業を行うメソッドを呼び出すことは一般的に不快ですが、通常、何かが意図したよりも複雑であるという匂いがします。

于 2012-05-14T19:30:45.453 に答える
3

深さ優先、プレオーダーウォーク。

Andersは良い点を述べています。Javaは暗黙的にネイティブタイプのフィールドのみを初期化します。オブジェクトフィールドはオブジェクトへの単なる参照であるため、実際には初期化されていますが、に初期化されていnullます。

于 2012-05-14T19:31:09.893 に答える
0

継承の場合にParent-Subクラスのコンストラクターを呼び出す順序は、Parentクラスのコンストラクターが常に最初に呼び出され、次にChildクラスのコンストラクターが呼び出されるというものです。

Subクラスは、明示的に指定されていない場合、デフォルトでSuper()を使用して基本クラスのコンストラクターを呼び出します。

于 2013-12-09T12:28:33.663 に答える