我正在编写一个简单的游戏,在其中我使用一个枚举,CommandManager,来存储关于可能的命令以及每个命令的作用的信息。此枚举的主要目的是能够打印出可用命令的菜单,以及用于检查输入并执行与该输入相关的操作。我的问题在于第二次使用,我使用switch语句根据用户的输入确定用户想要做什么。当尝试使用枚举的属性(通过getter方法)作为案例标签时,我遇到了一个编译错误。提供的错误消息是,大小写表达式必须是常量表达式。鉴于CommandManager的属性被声明为final,我认为枚举的属性根本不能在switch语句中使用,对吗?如果是这样,为什么?
以下代码的简化版本,以防出错。
方法代码:
void interpretInput() {
String command = input.getInput();
if (command.length() == 2) {
switch (command) {
case CommandManager.MAINMENU.getCommand(): goToMainMenu();
break;
case CommandManager.NEWGAME.getCommand(): startNewGame();
break;
case CommandManager.LISTGAMES.getCommand(): listSavedGames();
break;
case CommandManager.EXITGAME.getCommand(): exitGame();
break;
case CommandManager.HELPMENU.getCommand(): listAllCommands();
break;
}
}
}
枚举代码:
public enum CommandManager {
NEWGAME("!n", "New game"),
MAINMENU("!m", "Go to main menu"),
EXITGAME("!q", "Exit Battleships"),
LISTGAMES("!g", "List saved games"),
HELPMENU("!h", "Open help menu"),
LOADGAME("!l", "Load a new game"),
SAVEGAME("!s", "Save current game");
private final String command;
private final String menuOption;
CommandManager(String aCommand, String anOption) {
command = aCommand;
menuOption = anOption;
}
String getCommand() {
return command;
}
String getMenuOption() {
return menuOption;
}
}
我会通过使用Map来帮助动作设计模式来做不同的事情。
首先在CommandManager枚举中添加一个方法,该方法将命令字符串转换为CommandManager对象,例如:
public static CommandManager getCommandManager(String command) {
for (CommandManager cManager : CommandManager.values()) {
if (command.equals(cManager.getCommand())) {
return cManager;
}
}
throw new IllegalArgumentException(command);
}
例如,
public enum CommandManager {
NEWGAME("!n", "New game"),
MAINMENU("!m", "Go to main menu"),
EXITGAME("!q", "Exit Battleships"),
LISTGAMES("!g", "List saved games"),
HELPMENU("!h", "Open help menu"),
LOADGAME("!l", "Load a new game"),
SAVEGAME("!s", "Save current game");
private final String command;
private final String menuOption;
CommandManager(String aCommand, String anOption) {
command = aCommand;
menuOption = anOption;
}
String getCommand() {
return command;
}
String getMenuOption() {
return menuOption;
}
// ************ ADD THIS! *******
public static CommandManager getCommandManager(String command) {
for (CommandManager cManager : CommandManager.values()) {
if (command.equals(cManager.getCommand())) {
return cManager;
}
}
throw new IllegalArgumentException(command);
}
}
然后,为使用该映射的代码提供一个映射,该映射将每个CommandManager映射为一个Runnable,并填充该映射:
public class TestEnum {
private Map<CommandManager, Runnable> commandMap = new EnumMap<>(CommandManager.class);
public TestEnum() {
commandMap.put(CommandManager.MAINMENU, () -> goToMainMenu());
commandMap.put(CommandManager.MAINMENU, () -> goToMainMenu());
commandMap.put(CommandManager.NEWGAME, () -> startNewGame());
commandMap.put(CommandManager.LISTGAMES, () -> listSavedGames());
commandMap.put(CommandManager.EXITGAME, () -> exitGame());
commandMap.put(CommandManager.HELPMENU, () -> listAllCommands());
}
然后使用它!
void interpretInput(String command) {
CommandManager cManager = CommandManager.getCommandManager(command);
commandMap.get(cManager).run();
}
你必须使用一些不同的方法。您可以在枚举内编写静态方法,将命令字符串转换为CommandManager枚举:
public static CommandManager fromCommand(String command) {
for (CommandManager commandManager : values()) {
if (commandManager.getCommand().equals(command)) {
return commandManager;
}
}
return null; // or throw exception, whatever fits best for your code
}
然后,您可以调用此方法来获取en enum对象,并使用switch语句执行任何您想要的操作:
String command = input.getInput();
CommandManager commandManager = CommandManager.fromCommand(command);
if (commandManager != null) {
switch (commandManager) {
case MAINMENU:
goToMainMenu();
break;
case NEWGAME:
startNewGame();
break;
case LISTGAMES:
listSavedGames();
break;
case EXITGAME:
exitGame();
break;
case HELPMENU:
listAllCommands();
break;
default:
throw new IllegalArgumentException("Unknown command: " + commandManager);
}
}
我认为枚举的属性不能用在开关语句中,这是对的吗?
你是。
如果是这样,为什么?
因为switch语句的“标签”需要是编译时常数,并且枚举的属性不符合条件。
它们需要是编译时常量的原因是编译器需要检查开关标签是否不同。它不允许这样的事情
switch (someValue) {
case A.method(): doA();
case B.method(): doB();
}
其中<代码>A。方法()和。结果表明,method()具有相同的值。如果事例表达式不是编译时常量表达式,则编译器无法检测到问题。(方法调用从来不是编译时常量表达式。)
问题内容: (注:编辑过的问题;先前的意图不明确) 考虑以下代码: 此代码可以正常工作。 但是,如果我替换: 与: 然后编译器抱怨: java:/path/to/Foo.java:whatever:枚举开关大小写标签必须是枚举常量的非限定名称 (要求内联常量的一个原因是switch语句在每种情况下都需要常量,并且两个这样的常量值可能都不相同。编译器在编译时检查switch语句中是否有重复的常量值;
(注:经编辑的问题;事先意图不明确) 与: 在JLS的什么地方定义了语句中的值必须以这种方式编写?
问题内容: 我正在使用JavaScript将对象序列化为JSON字符串, 我注意到只有可枚举的对象属性才被序列化: [ 笔 ] 我想知道为什么会这样?我已经通过搜索MDN页面中,json2解析器文档。我找不到任何地方记录此行为。 我怀疑这是使用仅通过[[enumerable]]属性的循环(至少在情况下)的结果。可以使用类似的方法同时返回可枚举和不可枚举的属性。不过,这可能会导致序列化(由于反序列化
问题内容: 我想知道为什么在Java语言中a 不能扩展。 我不是在谈论一个延伸的(这不能做,因为Java没有多重继承,而Š隐含延长),但一类的以只添加额外的方法,而不是额外的枚举值。 就像是: 要这样使用: 因此,有人可以对此限制提供理由(或将我指向正确的JLS部分)吗? 问题答案: 我认为 他们这样做 的答案来自以下问题: 在您的示例中,如何实例化MyClass?用户永远不会(通过)显式实例化枚
问题内容: Java不允许枚举位于接口内部,但是默认情况下,接口内部的每个数据成员都是。有人可以澄清吗? 问题答案: 枚举不能是最终的,因为编译器将为程序员明确为其定义实现的每个枚举条目生成子类。 此外,根据JLS第8.9节,没有实例具有自己的类主体的枚举是隐式最终的。
编译器声称 的末尾缺少一个返回语句。代码如下: 编译器是否正确?(Android Studio) 如果是这样,在什么情况下可以到达方法的末尾?我认为不能是并且所有枚举都包含在开关语句中,在任何情况下返回语句都会离开方法。不能是,因为方法如果结果是,则会引发异常。 如果没有,你会用< code > return null//never behind 标记方法的(希望)不可到达的一端,还是抛出一个<