java - 创建控制台命令列表——如何正确使用 Java

标签 java enums switch-statement ordinal

对于我用 Java 编写的作业(我是新手),我遇到了创建控制台命令列表的问题。用户将面对一组命令,他/她将在其中选择一个数字。像这样:

Enter your choice:
0) Create a Table
1) List All Tables
2) Delete a Table
3) Insert a Record
4) List All Records
5) Delete a Record
6) Find a Record(by =)
7) Find a Record(by >)
8) Find a Record(by <)
9) Exit

我做的第一种方法如下(不需要的代码部分被截断):

...

outerLoop: while (true) {
    Scanner s = new Scanner(System.in);
    try {
        while (true) {
            System.out.println("Enter your choice:");
            displayChoiceList();
            int choice = s.nextInt();
            switch (choice) {
            case 1:
                processTableCreation();
                break;
            case 2:
                catalog.listAllTables();
                break;
            case 3:
                System.out.println("Enter the name of table:");
                String tableName = s.nextLine();
                catalog.deleteTable(tableName);
                break;
            case 4:
                processRecordInsertion();
                break;
            case 5:
                processListAllRecords();
                break;
            case 6:
                processDeleteRecord();
                break;
            case 7:
                processFindRecord(Constants.Operator.EQUAL);
                break;
            case 8:
                processFindRecord(Constants.Operator.SMALLER);
                break;
            case 9:
                processFindRecord(Constants.Operator.GREATER);
                break;
            case 10:
                break outerLoop;
            }
        }
    } catch (IllegalArgumentException e) {
        System.out.println("Error: " + e.getMessage());
    } catch (IOException e) {
        System.out.println(e.getMessage());
        return;
    }
}

...

private static void displayChoiceList() {
    String[] choices = new String[] { "Create Table", "List All Tables",
            "Delete a Table", "Insert a Record to a Table",
            "List all records", "Delete a record",
            "Find by Primary Key(=)", "Find by Primary Key(<)",
            "Find by Primary Key(>)", "Exit" };
    int id = 0;
    for (String choice : choices) {
        System.out.println((id + 1) + ") " + choice);
        ++id;
    }
}

然后,认为这很丑陋,为了试验枚举,我尝试了以下方法:

private enum Command {
    CREATE_TABLE("Create a Table"),
    LIST_ALL_TABLES("List All Tables"),
    DELETE_TABLE("Delete a Table"),
    INSERT_RECORD("Insert a Record"),
    LIST_ALL_RECORDS("List All Records"),
    DELETE_RECORD("Delete a Record"),
    FIND_RECORD_EQ("Find a Record(by =)"),
    FIND_RECORD_GT("Find a Record(by >)"),
    FIND_RECORD_LT("Find a Record(by <)"),
    EXIT("Exit");

    private final String message;

    Command(String message) {
        this.message = message;
    }

    public String message() { return this.message; }
}

...

outerLoop: while (true) {
    Scanner s = new Scanner(System.in);
    try {
        while (true) {
            System.out.println("Enter your choice:");
            displayChoiceList();
            int choice = s.nextInt();

            if (choice == Command.CREATE_TABLE.ordinal())
                processTableCreation();
            else if (choice == Command.LIST_ALL_TABLES.ordinal())
                catalog.listAllTables();
            else if (choice == Command.DELETE_TABLE.ordinal()) {
                System.out.println("Enter the name of table:");
                String tableName = s.nextLine();
                catalog.deleteTable(tableName);                     
            }
            else if (choice == Command.INSERT_RECORD.ordinal())
                processRecordInsertion();
            else if (choice == Command.LIST_ALL_RECORDS.ordinal())
                processListAllRecords();
            else if (choice == Command.DELETE_RECORD.ordinal())
                processDeleteRecord();
            else if (choice == Command.FIND_RECORD_EQ.ordinal())
                processFindRecord(Constants.Operator.EQUAL);
            else if (choice == Command.FIND_RECORD_LT.ordinal())
                processFindRecord(Constants.Operator.SMALLER);
            else if (choice == Command.FIND_RECORD_GT.ordinal())
                processFindRecord(Constants.Operator.GREATER);
            else if (choice == Command.EXIT.ordinal())
                break outerLoop;
            else
                System.out.println("Invalid command number entered!");
        } 
    } catch (IllegalArgumentException e) {
        System.out.println("Error: " + e.getMessage());
    } catch (IOException e) {
        System.out.println(e.getMessage());
        return;
    }
}

...

private static void displayChoiceList() {
    for (Command c : Command.values())
        System.out.println(c.ordinal() + ") " + c.message());
}

实际上,我的想法是使用 Enum 的 in switch 及其序数值,但 Java 不允许在 switch 情况下使用非常量值。解决这个问题的正确方法是什么?最优雅/可扩展/灵活?非常感谢任何建设性意见!

最佳答案

您可以使用 Command.values(),它包含按顺序排列的枚举:

switch (Command.values[number]) {
case CREATE_A_TABLE:
...
}

一种更优雅和可维护的方法是使用多态性来消除 switch 语句:

abstract class Command {
    private String name;

    protected Command(String name) {
        this.name = name;
    }

    @Override public String toString() {
        return name;
    }

    public abstract void execute();
}

和其他地方:

Command[] commands = {
    new Command("Create a table") {
        @Override public void execute() {
            // code to create a table
        }
    },
    new Command("List all tables") {
        @Override public void execute() {
            // code to list all tables
        }
    }
};

for (int i = 0; i < commands.length; i++) {
    System.out.println(i + ":" + command);
}

int number = getInput();

commands[number].execute();

优点:

  • 更短、更清晰的代码
  • 编译器检查每个命令是否已实现(使用 switch 语句,您可以忘记添加 case 语句,这种错误只会在运行时发生。当然,如果您忘记了 case when,一个好的编译器会发出警告切换枚举,但比编译错误更容易错过警告)。 ==> 在维护期间更稳健。

关于java - 创建控制台命令列表——如何正确使用 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5904431/

相关文章:

c# - If Condition inside 开关盒

assembly - PIC汇编器中如何进行bank切换?

java - 如何使用java在android中绘制带有圆角矩形的二维码?

asp.net-mvc - 如何防止 EnumDropDownListFor 将 0 设置为 optionLabel 值?

c# - 如何将枚举绑定(bind)到 telerik :RadGrid in ASP WebForms

c++ - 内部类访问外部类嵌套枚举

java - 在android中解析并存储json响应

java - 多次尝试修复 : Malformed input or input contains unmappable chacraters 后,Eclipse 中出现连续 Git 错误

java - 在 Jenkins 上运行 TestFX 时如何避免 HeadlessException?

switch-statement - 高效开关需要自认证吗?