我创建了一个Enum来定义某些动作。针对外部API编程我被迫使用Integer
来表达此操作。这就是为什么我在我的Enum中添加了一个整数实例字段。这应该与Joshua Bloch的Effective Java一致,而不是依赖于ordinal()
或使用values()[index]
的Enum常量的顺序。
public enum Action {
START(0),
QUIT(1);
public final int code;
Protocol(int code) {
this.code = code;
}
}
我从API获得一个整数值what
,现在我想从中创建一个Enum值,我该如何以最通用的方式实现它?
Action valueOf(int what) {
return new Action(what);
}
当然,我总是可以创建一个switch-case语句并添加所有可能的代码并返回适当的常量。但我想避免在两个地方同时定义它们。
答案 0 :(得分:5)
如果您有很多这样的话,可以使用HashMap<Integer, Action>
:
private static final Map<Integer, Action> actions = new HashMap<>(values().size, 1);
static {
for (Action action : values())
actions.put(action.code, action);
}
// ...
public static Action valueOf(int what) {
return actions.get(what);
}
如果您要获得大量Action
值,这很有用,因为HashMap
查找是O(1)。
答案 1 :(得分:1)
如果您确定您的代码始终是连续的并且从0开始,则最有效的选项是
public enum Action {
START(0),
QUIT(1);
public static final Action[] ACTIONS;
static {
ACTIONS = new Action[values().length];
for(Action a : values()) {
ACTIONS[a.code] = a;
}
}
public final int code;
Protocol(int code) {
this.code = code;
}
}
答案 2 :(得分:0)
我个人会保持简单(YAGNI)并使用序号值但:
枚举代码:
public enum Action {
START(0),
QUIT(1);
private final int code;
Action(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static Action of(int code) {
try {
return Action.values()[code];
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("not a valid code: " + code);
}
}
}
<强>测试强>
@Test
public testActionEnumOrder() {
int i = 0;
for (Action a : Action.values()) {
assertEquals(a.getCode(), i++);
}
}
例如,如果您将QUIT(1)
更改为QUIT(2)
,则测试将失败。当发生这种情况时,您可以使用HashMap或查找循环。