关于构造函数的奇怪的NullPointerException

时间:2012-10-18 03:54:43

标签: java swing constructor nullpointerexception

我正在聊天客户端/服务器上工作。在客户端中,我有一个名为ClientGui的类,以及一个名为InputPane的子类,它扩展了JPanelClientGui处理与GUI相关的客户端事务的主要部分,但InputPane仅处理来自用户的输入。

在尝试在NullPointerException类的InputPane对象中设置字体时,我不断变得奇怪ClientGui。以下是我的一些代码:

public ClientGui() {
    // configure JFrame

    this.serverOutput = new JTextPane();
    this.input = new InputPane();

    // configure JScrollPane

    // configure other objects

    // various set up methods

    frame.add(scrollPane, BorderLayout.CENTER);
    frame.add(input, BorderLayout.PAGE_END);
}

如您所见,input对象正在初始化。这是它的构造函数:

public InputPane() {
        this.inputField = new JTextField();
        this.send = new JButton("Send");

        // set size

        this.setFont(getFont());

        // various methods

        // add components
    }

当我尝试设置字体时,它会抛出NullPointerException。通过各种println()调用,我发现inputFieldsend为空。我尝试在构造函数中放置println()方法,但没有调用(和/或打印)。

我很困惑。如果有人能给出解释,那将会有很大帮助。谢谢。

编辑:这是StackTrace:

Exception in thread "main" java.lang.NullPointerException
at net.dean.tcp.client.gui.ClientGui$InputPane.setFont(ClientGui.java:518)
at javax.swing.LookAndFeel.installColorsAndFont(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installDefaults(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installUI(Unknown Source)
at javax.swing.JComponent.setUI(Unknown Source)
at javax.swing.JPanel.setUI(Unknown Source)
at javax.swing.JPanel.updateUI(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at net.dean.tcp.client.gui.ClientGui$InputPane.<init>(ClientGui.java:496)
at net.dean.tcp.client.gui.ClientGui.<init>(ClientGui.java:138)
at net.dean.tcp.client.gui.ClientGui.main(ClientGui.java:44)

编辑2 :以下是ClientGui$InputPane.setFont(Font)方法:

public void setFont(Font f) {
        super.setFont(f);
        inputField.setFont(f);
        send.setFont(f);

        Dimension size = getSizeFromFont(); 
        // Dimension based on getFont()'s height

        send.setPreferredSize(size);
        inputField.setPreferredSize(size);
    }

2 个答案:

答案 0 :(得分:4)

问题是Swing框架将setFont作为JPanel构造函数的一部分进行调用。由于这在构造函数的主体之前执行,因此在InputPane.setFontsend成员变量初始化之前调用inputField。我认为,这里唯一干净的解决方案是在InputPane.setFont

中进行显式空值检查
public void setFont(Font f) {
    super.setFont(f);
    if (inputField != null) {
        inputField.setFont(f);
    }
    if (send != null) {
        send.setFont(f);
    }

    Dimension size = getSizeFromFont(); 
    // Dimension based on getFont()'s height

    if (send != null) {
        send.setPreferredSize(size);
    }
    if (inputField != null) {
        inputField.setPreferredSize(size);
    }
}

(您可以重新组织调用以减少空值检查。)

顺便说一句,这是为什么it is bad practice to call an overridable method from a constructor的一个很好的例子。但Swing就是这样,并且抱怨它没有任何利润,所以我会停在这里。 :)

答案 1 :(得分:0)

使用setFont设置字体时,您将从getFont方法获取字体并进行设置。这个getFont()更有可能返回NULL,这可能是原因。另外在我看来inputFieldsend对象在inputPane对象中都不能为NULL,除非你明确地将它们设为NULL。