Java 中使用 Runnables 的带有枚举的 nullPointerException

nullPointerException with enum using Runnables in Java

我已经通读了 nullPointerExceptions 的解释,我知道当指向的值具有 null 值时,就好像它在引用一个对象一样,但我无法理解为什么我会得到一个枚举的使用有点像 switch 语句,但当然不是实际使用 switch 语句。正如我提到的,预期的行为应该像一个 switch 语句。也许我缺少对枚举和 NPE 概念的基本理解。我的代码如下。 (此代码适用于 Enigma 密码机)

void displayMenu() {
    System.out.println("MAIN MENU");
    System.out.println();
    Stream.of(menuChoice.values()).map(stream -> stream.ordinal() + ". " + stream.msg).forEach(System.out::println);
    System.out.println();
}

public enum menuChoice {

    QUIT("Quit the Enigma", EnigmaMachine.instance.quitAction),
    ENCRPYT("Encrypt", EnigmaMachine.instance.encryptAction),
    DECRYPT("Decrypt", EnigmaMachine.instance.decryptAction);
    private String msg;
    public Runnable action;

    private menuChoice(String message, Runnable r) {
        this.msg = message;
        this.action = r;
    }
}

menuChoice getUserChoice() {
    System.out.print("Please enter your choice: ");
    int choice = s.nextInt();
    return menuChoice.values()[choice];
}

在 QUIT 常量上,我正在使用一个可运行的设置:

final Runnable quitAction = () -> {
    EnigmaMachine.instance.running = false;
};

堆栈跟踪是这样的:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at enigmamachine.EnigmaMachine.displayMenu(EnigmaMachine.java:24)
    at enigmamachine.EnigmaMachine.<init>(EnigmaMachine.java:85)
    at enigmamachine.EnigmaMachine.main(EnigmaMachine.java:91)
Caused by: java.lang.NullPointerException
    at enigmamachine.EnigmaMachine$menuChoice.<clinit>(EnigmaMachine.java:30)
    ... 3 more
Java Result: 1

我的构造函数是这样的:

public EnigmaMachine() {
    this.running = true;
    while (this.running) {
        displayMenu();
        getUserChoice().action.run();
    }
}

对象实例是在我的代码底部的 main 函数之上定义的。

static EnigmaMachine instance;
public static void main(String[] args) {
    instance = new EnigmaMachine();
}

我不一定在寻找解决方案,但也许是对我正在处理的事情的更相关的解释。 非常感谢。

您遇到这个问题只是因为 EnigmaMachine.instance 在此处 QUIT("Quit the Enigma", EnigmaMachine.instance.quitAction) 调用时仍然是 null。你不应该在你的构造函数中调用 displayMenu() 因为它太早了,你应该调用它一个方法来避免这个问题。

例如,您可以向 class 添加一个方法开始,如下所示:

    public void start() {
        this.running = true;
        while (this.running) {
            displayMenu();
            getUserChoice().action.run();
        }
    }

然后在main方法中调用next

    instance = new EnigmaMachine();
    instance.start();