虽然@Eran 的回答是正确的,但我想提出一种不同的方法,将枚举与外部编码的翻译一起封装起来。考虑一下:
public class EnumDemo
{
public static enum ActionType
{
Incorrect(""),
RotF("rotate_forw"),
RotB("rotate_back"),
ShiftF("shift_forw"),
ShiftB("shift_back");
private String code;
private ActionType(String code)
{
this.code = code;
}
public static ActionType fromString(String code)
{
return Arrays.stream(ActionType.values())
.filter(v->v.code.equals(code))
.findFirst()
.orElse(ActionType.Incorrect);
}
}
public static void main(String[] args)
{
String[] testData = {
"rotate_forw",
"rotate_back",
"shift_forw",
"shift_back",
"junk",
null };
Arrays.stream(testData)
.forEach(t->System.out.printf("\"%s\" -> ActionType.%s\n", t, ActionType.fromString(t)));
}
}
这使用了枚举常量可以具有关联数据的事实。我添加了一个实例变量code 来保存每个枚举值的外部编码。然后我在枚举中添加了一个静态fromString(String code) 方法,用于在值列表中查找提供的代码。对于 4 种可能性,一个简单的线性搜索,相当于您的 if-then-else 级联,工作正常。如果有几十个或更多,我会设置一个Map<String,ActionType> 来处理转换。
使用流的搜索有一些解释。
- 首先创建一个枚举值的
Stream
- 过滤它以仅包含
code 与所需代码匹配的枚举值(应该只有一个)
- 选择第一个条目,它以
Optional 返回。如果未找到任何内容(即代码无效),Optional 将为空。
- 如果值存在则使用
orElse 方法返回值,如果不存在则使用ActionType.Incorrect。
乍一看,这可能看起来效率低下,因为人们预计 filter() 谓词必须扫描整个流,即使所需的元素出现得早。这是 Streams 的一个非常棒的特性——所有中间流都是“惰性的”,所以如果过滤器尽早找到所需的条目,它就不会遍历整个列表。详情请见this question。
输出:
"rotate_forw" -> ActionType.RotF
"rotate_back" -> ActionType.RotB
"shift_forw" -> ActionType.ShiftF
"shift_back" -> ActionType.ShiftB
"junk" -> ActionType.Incorrect
"null" -> ActionType.Incorrect
最后一个测试用例显示代码是空安全的。
最大的优点是映射与枚举本身位于同一位置,因此您在添加或删除枚举值时不必寻找代码。你也不能忘记定义映射,因为它是枚举的构造函数所需要的。