TooLateTheHero TooLateTheHero - 7 months ago 7
Java Question

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.

Answer

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();
Comments