简体   繁体   中英

nullPointerException with enum using Runnables in Java

I have read through the explanations of nullPointerExceptions and I know that it is when a value being pointed to has a null value as though it is referencing an object but I just cannot get my head around why I am getting one with an enum being used somewhat like a switch statement, but of course not actually using a switch statement. The expected behaviour, like I mentioned, should be like a switch statement. Perhaps I am missing a fundamental understanding of both the enum and NPE concepts. My code is as follows. (This code is for an Enigma cipher machine)

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];
}

On the QUIT constant I am using a runnable that sets:

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

The stacktrace is like this:

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

My constructor is like this:

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

Object instance is defined just above main function which is at the bottom of my code.

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

I am not necessarily looking for a solution, but perhaps a more relatable explanation of what I am dealing with. Many thanks.

You get this issue simply because EnigmaMachine.instance is still null when it is call here QUIT("Quit the Enigma", EnigmaMachine.instance.quitAction) . You should not call displayMenu() inside your constructor as it is too soon, you should call it a method to avoid this issue.

You could add for example a method start to your class as below:

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

Then call it in the main method as next

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM