2

私はこれを尋ねるのは嫌いですが、コンストラクターでこれらの変数を明確に初期化したにもかかわらず、2 つのグローバル変数weakAcidとで NullPointerException を取得しています。weakBase私のコードは以下で、エラーは addComponents() メソッドにあり、正確な行panel.add(weakAcid, c)です。デバッグしたところ、両方のフィールドの初期化に失敗したことがわかりました。おそらく助けますか?

スタックトレース:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at java.awt.Container.addImpl(Unknown Source)
at java.awt.Container.add(Unknown Source)
at gametype.AcidBaseGame.addComponents(AcidBaseGame.java:112)
at gametype.Game.<init>(Game.java:55)
at gametype.SolubilityGame.<init>(SolubilityGame.java:17)
at gametype.AcidBaseGame.<init>(AcidBaseGame.java:25)
at gui.GameFrame.actionPerformed(GameFrame.java:132)

public class AcidBaseGame extends SolubilityGame
{

private JButton weakAcid;
private JButton weakBase;

private int buttonIndex;

public AcidBaseGame()
{
    /* hidden code to save space */

    weakAcid = new JButton("Weak Acid");
    weakBase = new JButton("Weak Base");

    endDisplay = new JLabel();

    //actionlisteners to buttons
    choice1.addActionListener(this);
    choice2.addActionListener(this);
    weakAcid.addActionListener(this);
    weakBase.addActionListener(this);

    this.addComponents();

}


private void setChemical()
{
    //hidden code
}

public void addComponents() 
{

    GridBagConstraints c = new GridBagConstraints();

            //initializes fine
    c.fill = GridBagConstraints.CENTER;
    c.gridx = 1;
    c.gridy = 0;
    panel.add(chemicalLabel, c);

    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.gridy = 1;
    panel.add(choice1, c);

    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 2;
    c.gridy = 1;
    panel.add(choice2, c);

            //error
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.gridy = 2;
    panel.add(weakAcid, c);

    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 2;
    c.gridy = 2;
    panel.add(weakBase, c);

    c.fill = GridBagConstraints.CENTER;
    c.gridx = 1;
    c.gridy = 3;
    panel.add(endDisplay, c);

}

public void determineCorrect() 
{
       //hidden code
}

public void actionPerformed(ActionEvent arg0)
{

    //hidden code

}

}

4

2 に答える 2

4

私の推測では、親クラスのコンストラクターがオーバーライドされたaddComponents()メソッドを呼び出しています。これを行うとaddComponents()、子クラスのメソッドが呼び出され、コンポーネントが初期化される前に呼び出されます。

コンストラクターにオーバーライド可能なメソッドを呼び出すと危険があることに注意してください。これが、この種のことを避ける必要がある理由の 1 つです。ここで継承を使用する必要があるかどうかを再評価することもできますが、実際にはそうすべきではないと思います。


編集:
あなたはコメントで述べています:

以前のバージョンでは super() を呼び出していましたが、初期化する前に addComponents() を呼び出していることに気付きました。super() を使用しないようにコンストラクターを変更しました。

super()コンストラクターは、必要に応じて自動的に呼び出されるため、呼び出す必要はありません。できることは、必要に応じて addComponents() を呼び出さないスーパー クラスの特定のコンストラクターを呼び出すことだけです。私の提案: この GUI には継承さえ使用しないでください。付加価値はなく、リスクを伴います。

于 2013-05-11T17:23:47.857 に答える