假设我有一个枚举:
enum E {
A, B, C;
}
如this answer lucasmo所示,枚举值按照初始化的顺序存储在静态数组中,稍后您可以使用{{1}检索(克隆)此数组}}
现在假设我要实现E.values()
和E#getNext
,以便所有以下表达式都评估为E#getPrevious
:
true
E.A.getNext() == E.B
E.B.getNext() == E.C
E.C.getNext() == E.A
E.A.getPrevious() == E.C
E.B.getPrevious() == E.A
E.C.getPrevious() == E.B
的当前实现如下:
getNext
和public E getNext() {
E[] e = E.values();
int i = 0;
for (; e[i] != this; i++)
;
i++;
i %= e.length;
return e[i];
}
的类似方法。
然而,这段代码充其量似乎很麻烦(例如,“空”getPrevious
循环,可论证滥用计数器变量,最坏情况下可能是错误的(可能反思)。
在Java 7中为枚举类型实现for
和getNext
方法的最佳方法是什么?
注意:我不打算将此问题视为主观。我对“最佳”实现的请求是要求实施最快,最干净,最易维护的简写。
答案 0 :(得分:74)
试试这个:
public static enum A {
X, Y, Z;
private static A[] vals = values();
public A next()
{
return vals[(this.ordinal()+1) % vals.length];
}
previous()
的实施仅作为练习,但请记住in Java, the modulo a % b
can return a negative number。
编辑:根据建议,制作values()
数组的私有静态副本,以避免每次调用next()
或previous()
时进行数组复制。
答案 1 :(得分:7)
或者,人们可以按照以下想法行事:
public enum SomeEnum {
A, B, C;
public Optional<SomeEnum> next() {
switch (this) {
case A: return Optional.of(B);
case B: return Optional.of(C);
// any other case can NOT be mapped!
default: return Optional.empty();
}
}
注意:
ordinal()
。当然这意味着更多的代码;但它也迫使作者考虑添加新常量或删除现有常量意味着什么。当依赖序数时,隐式假设是顺序基于用于枚举常量声明的顺序。因此,当有人在6个月后回来并且必须添加新的常量时,他必须明白新的常量Y需要X, Y, Z
...而不是仅仅追加X, Z, Y
!答案 2 :(得分:-1)
public enum Three
{
One, Two, Three;
static
public final Three[] values = values();
public Three prev() {
return values[(ordinal() - 1 + values.length) % values.length];
}
public Three next() {
return values[(ordinal() + 1) % values.length];
}
}