Java类初始化难题

时间:2010-12-11 07:13:06

标签: java inheritance access-modifiers

我正在使用NetBeans的GUI Designer来创建一些JDialog,然后我从我自己的EditorDialog类中继承它。

在进一步讨论之前,请考虑以下示例代码:

class MyDialog extends EditorDialog {
    private Color someVariableThatTheGuiNeeds = new Color(0,50,100);

    public MyDialog() {
        super(true);
    }

    //<auto-generated>
    private void initComponents() { //note this is private!
        //...
    }
    //</auto-generated>
}

abstract class EditorDialog extends JDialog {
    public EditorDialog() {
        super(null,true);
    }
    public EditorDialog(boolean stuffNeedsDone) {
        super(null,true);
        //initComponents();
        doStuffAfterGuiInitialized();
    }
}

问题是,我不能从我的超类中调用initComponents(),因为它是私有的。

为了解决这个问题,我尝试了一种解决方法:

//in EditorDialog
public EditorDialog(boolean stuffNeedsDone) {
    super(null,true);
    workaround();
    doStuffAfterGuiInitialized();
}
protected abstract void workaround();

//in MyDialog
@Override
protected void workaround() {
    initComponents();
}

当然,这不起作用,因为someVariableThatTheGuiNeeds由于初始化的发生方式被调用initComponents()时未初始化:

  • new MyDialog()
    • super(this)
      • EditorDialog(boolean)被调用
        • super(null,true)被调用,JDialog做事
        • EditorDialog的实例变量已初始化
        • workaround()
        • initComponents()
          • doSomethingWith(someVariableThatTheGuiNeeds) - &gt; NullPointerException 因为someVariableThatTheGuiNeeds尚未初始化
    • NOW someVariableThatTheGuiNeeds已初始化

此外,我无法在initComponents()中创建非私有摘要EditorDialog,因为覆盖时的可见性只会变得更加公开。

那么,我怎样才能解决这个问题,而不是太过于苛刻?

(如果您不熟悉NetBeans,我无法编辑自动生成的代码,并且没有选项(我可以找到)来更改initComponents()方法上的访问修饰符。

2 个答案:

答案 0 :(得分:1)

在任何情况下,您的构造函数都不应该调用非private方法。如果在创建对话框后需要对其进行初始化,则可以创建一个init()方法,该方法应在构造函数完成后调用。

注意,方法名称doStuffAfterGuiInitialized()表示有点误解。在构造函数完成之后,GUI或甚至实例都不会完全初始化。

答案 1 :(得分:0)

这是java中常见的问题。 Instanciation不是子类化的朋友。

许多人使用间接解决方案:一旦对象完全构建,就调用init()方法。

这通常是通过工厂自动完成的。 所有注入框架(如Spring)都会定期执行此操作。