java JMenuItem Nullpointerexception(初始化错误,覆盖摆动 class)

java JMenuItem Nullpointerexception (error on initialization, when overriding a swing class)

我正在做一个项目并取得了很好的进展,直到我偶然发现了一个意外的异常。它是由启动 JMenuItem 引起的,有点令人惊讶,因为我之前做过类似的事情。我发现 class (class2) 工作正常,如果它不是 JMenuItem (class4) 的子 class。我也找到了解决方法 (class3),但我仍然想知道我做错了什么。我搜索了一个答案,但没有找到答案,可能是因为搜索条件不佳。有人有什么想法吗?

import javax.swing.JMenuItem;

class class1 {
    public static void main(String[] f) {
        System.err.println(new class3(0));
        System.err.println(new class3(1));
        System.err.println(new class4(0));
        new class2(1);
    }
}

class class2 extends JMenuItem {
    static String[] a;
    int b;

    {
        a = new String[2];
        a[0] = "c";
        a[1] = "d";
    }

    public class2(int e) {
        super();
        b = e;
    }

    public String getText() {
        return a[b];
    }

    public String toString() {
        return class2.class + ": " + b + ", " + getText();
    }
}

class class3 extends JMenuItem {
    static String[] a;
    int b;

    {
        a = new String[2];
        a[0] = "c";
        a[1] = "d";
    }

    public class3(int e) {
        super();
        b = e;
    }

    public String getText() {
        if ( b == 0 ) return "g";
        return a[b];
    }

    public String toString() {
        return class3.class + ": " + b + ", " + getText();
    }
}

class class4 {
    static String[] a;
    int b;

    {
        a = new String[2];
        a[0] = "c";
        a[1] = "d";
    }

    public class4(int e) {
        super();
        b = e;
    }

    public String getText() {
        return a[b];
    }

    public String toString() {
        return class4.class + ": " + b + ", " + getText();
    }
}

当我执行 class:

时,就会发生这种情况
$ javac class1.java 
$ java -showversion class1
java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)

class class3: 0, g
class class3: 1, d
class class4: 0, c
Exception in thread "main" java.lang.NullPointerException
    at class2.getText(class1.java:29)
    at javax.swing.AbstractButton.setModel(AbstractButton.java:1779)
    at javax.swing.JMenuItem.setModel(JMenuItem.java:173)
    at javax.swing.JMenuItem.<init>(JMenuItem.java:150)
    at javax.swing.JMenuItem.<init>(JMenuItem.java:110)
    at class2.<init>(class1.java:24)
    at class1.main(class1.java:8)

最后,一个 NullPointerException 问题不是你的typical NPE question

如果您查看 JMenuItem API 或给您的方法添加 @Override 注释,您会发现 public String getText() 是对超级方法的重写,特别是方法JMenuItem 的父级 AbstractButton,看起来超级的构造函数正在调用它,在调用您的实例初始化程序块之前调用它,这会导致您的 NPE。

此问题说明了在以下情况下可能发生的风险:

  • 您扩展了复杂的 classes。
  • 类 在其构造函数中调用非最终实例方法(Swing 作者这样做是可耻的)
  • 静态字段不是以静态方式初始化的。

适合您的解决方案包括:

  • 倾向于使用组合而不是继承,尤其是在处理大型和复杂的 classes 时。
  • 为您的静态字段使用静态初始化程序块。
  • 除非有明确的需要,否则避免使用静态字段。
  • 在创建方法时检查您是否在不知不觉中覆盖了实例方法。当我在不知不觉中为扩展 JPanel 的 class 覆盖 public int getX()public int getY() 然后想知道为什么我的布局管理器无法正常工作时,我尤其为此感到恼火。