Home > OS >  Storing/executing code fragments as variables in Java
Storing/executing code fragments as variables in Java

Time:02-20

I'm trying to create a console based Menu class. I want the class to contain an array (named options) of MenuOption objects which each have a label (String), text (String), and code (TBD) property. The idea is that I want users to input a string and the menu will execute the relevant code with something close to the following:

for (MenuOption option: options)
{
if (input.equals(option.label)) execute option.code;
}

I feel like theres probably a way to do this using lambda functions, but I've been hitting dead ends for the last couple of hours. Any suggestions are appreciated.

CodePudding user response:

This is the classic Java 8 version, fully implemented.

package stackoverflow;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Objects;

public class ConsoleMenu {

    static public class MenuOption {
        public final String     label;
        public final String     text;
        public final Runnable   code;
        public MenuOption(final String pLabel, final String pText, final Runnable pLambda) {
            label = pLabel;
            text = pText;
            code = pLambda;
        }
    }



    public static void main(final String[] args) throws IOException {
        final ArrayList<MenuOption> options = new ArrayList<>();
        options.add(new MenuOption("Option A", "A", () -> System.out.println("Hello this is A")));
        options.add(new MenuOption("Option B", "B", () -> {
            System.out.print("Hello this is B");
            System.out.println(" in multiple lines Lambda");
        }));


        System.out.println(" - - - Menu - - - ");
        for (final MenuOption mo : options) {
            System.out.println("\t"   mo.label   "\t"   mo.text);
        }
        System.out.println("Enter your choice:");
        try (final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));) {
            final String line = br.readLine().toLowerCase();
            for (final MenuOption mo : options) {
                if (Objects.equals(line, mo.text.toLowerCase())) {
                    System.out.println("You chose "   mo.label);
                    mo.code.run();
                    break;
                }
            }
        }

        System.out.println("All done.");
    }

}

CodePudding user response:

You’re on the right track. Try something like:

public record MenuOption(String label,
                         String text,
                         Runnable action) {
    // Deliberately empty.
}

You can, as you suspected, construct them with lambdas:

MenuOption printOption = new MenuOption(
    "Print",
    "Send formatted data to a printer",
    () -> printData());

MenuOption exitOption = new MenuOption(
    "Exit",
    "Close application",
    () -> System.exit(0));

If you’re stuck with an older version of Java, you can just make a regular class which is equivalent to a record:

public class MenuOption {
    private String label;
    private String text;
    private Runnable action;

    public MenuOption(String label,
                      String text,
                      Runnable action) {
        this.label = label;
        this.text = text;
        this.action = action;
    }

    public String getLabel() {
        return label;
    }

    public String getText() {
        return text;
    }

    public Runnable getAction() {
        return action;
    }
}
  • Related