5

我创建了一个枚举来定义某些操作。针对外部 API 进行编程我被迫使用 anInteger来表达这个动作。这就是为什么我在我的枚举中添加了一个整数实例字段。这应该与 Joshua Bloch 的 Effective Java 一致,而不是依赖于ordinal()Enum 常量的顺序或使用values()[index].

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 语句并添加所有可能的代码并返回适当的常量。但我想避免同时在两个地方定义它们。

4

3 回答 3

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)。

于 2013-01-18T18:12:15.480 回答
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;
     }
}
于 2013-01-18T18:26:39.770 回答
0

我个人会保持简单(YAGNI)并使用序数值但是

  • 我会将逻辑保留在枚举中,以确保外部代码不知道该实现细节并且不依赖它
  • 如果出现问题(即如果数字不是从 0 开始或不是递增的),我会确保我有一个失败的测试

枚举代​​码:

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 或查找循环。

于 2013-01-18T18:45:08.560 回答