1

有一个基类ServerAdapter

public abstract class ServerAdapter {
    public ServerAdapter() {
        initGUI();
    }

    protected abstract void initGUI();
}

还有一个继承的子类ServerAdapter

public abstract class LinuxServerAdapter extends ServerAdapter {
    protected CheckBox key = new CheckBox();

    public LinuxServerAdapter() {
        super();
    }

    @Override
    public void initGUI() {
        //NPE is thrown here, because key = null
        key.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                //Something happens here
            }
        });
    }
}

继承 LinuxServerAdapter 的端类:

public class MyLinuxServerAdapter extends LinuxServerAdapter {

    public MyLinuxServerAdapter() {
        super();
    }

    public static void main(String args[]) {
        ServerAdapter server = new MyLinuxServerAdapter();
    }
}

当我尝试在键上添加 clickHandler 时,会引发 NPE。

为什么key没有初始化?这是初始化顺序以特定方式工作的情况吗?

4

2 回答 2

5

只需在 init 方法中初始化即可。毕竟是这个目的。。

@Override
public void initGUI() {
    key = new CheckBox();
    key.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
            //Something happens here
        }
    });

父类在子类之前实例化。在您的顶级父类中,您调用initGUI()抽象方法,它的实现位于其尚未初始化其其他字段的子级中。将字段的实际初始化移至initGUI()方法是有意义的,它符合名称约定和您所获得的逻辑。

于 2013-05-23T13:57:58.740 回答
1

实例变量声明中的赋值,以及块内非静态块中的任何语句class,都在调用返回后运行。super()如果您从超类的构造函数调用子类的方法,它将使用未初始化的this.

这就是为什么有一条一般规则,即永远不要从构造函数中调用虚方法。

于 2013-05-23T14:02:30.797 回答