Java构造函数和字段初始化顺序 [英] Java Constructor and Field Initialization Order

查看:481
本文介绍了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< Shape>的值bag 目前为空。

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 之前初始化行李。)

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 中定义的方法 - 尚未初始化。事实上,你所做的实际上是一个非常微妙的bug 。你永远不应该从构造函数调用overridable(包括 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.

  • 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

这篇关于Java构造函数和字段初始化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆