Java enum auto-increment entries?
Does Java allow something like good ol' C or even C# in the sense that you can define an enum with fields that grow in value automatically, and start at an optionally given value?
E.g.
In C or C#开发者_开发知识库:
enum Foo { A = 10, B, C, D = 5000, E, Fish };
Yields A = 10, B = 11, C = 12, D = 5000, E = 5001, Fish = 5002.
In Java you can't specify the ordinal values explicitly at all. They always autoincrement, from 0, with no control over it.
If you want other custom values, you need to put them in constructor calls and store them yourself. You can get autoincrement, but it's icky as heck:
import java.util.EnumSet;
// Please don't ever use this code. It's here so you can point and laugh.
enum Foo
{
A(10), B, C, D(5000), E, Fish;
private static int nextValue;
private int value;
private Foo()
{
this(Counter.nextValue);
}
private Foo(int value)
{
this.value = value;
Counter.nextValue = value + 1;
}
public int getValue()
{
return value;
}
private static class Counter
{
private static int nextValue = 0;
}
}
public class Test
{
public static void main(String[] args)
{
for (Foo foo : EnumSet.allOf(Foo.class))
{
System.out.println(foo.name() + " " +
foo.ordinal() + " " +
foo.getValue());
}
}
}
Note the need for the nested class, because you can't access static fields within an enum constructor. Ick, ick, ick. Please don't do this.
This is a design choice of Java Enums to not support to change the ordinal values. Basically, they are not stable enough to depend on them. If you change the position of B and C in your example clients depending on the ordinal values are broken. This may happen unintentionally.
The problem is described in Effective Java Item 31: Use instance field instead of ordinals.
You can emulate the behavior in a stable manner:
enum X{
A(10), B(A), C(B), D(5000), E(D), F(E);
private final int value;
X(int value){
this.value = value;
}
X(X preceding){
this.value = preceding.getValue() + 1;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return this.name() + "(" + this.value + ")";
}
static {
Set<Integer> values = new HashSet<Integer>();
for(X x : X.values()) values.add(x.value);
assert(values.size() == X.values().length); //no duplicates
}
}
With this definition you may change the order of the values without breaking clients.
Calling for(X x : X.values()) System.out.println(x);
returns:
A(10)
B(11)
C(12)
D(5000)
E(5001)
F(5002)
精彩评论