public enum MyEnum
{
EnumValue1,
EnumValue2
}
MyEnum enumValue = (MyEnum) x; //Doesn't work???
尝试使用 MyEnum.values()[x]
,其中x
必须是0
或1
,即为该枚举的有效序数。
请注意,在Java中枚举实际上是类(枚举值也因此是对象),因此您不能将int
甚至Integer
强制转换为枚举。
MyEnum.values()[x]
是一项昂贵的操作。如果性能是一个问题,您可能希望这样做:
public enum MyEnum {
EnumValue1,
EnumValue2;
public static MyEnum fromInteger(int x) {
switch(x) {
case 0:
return EnumValue1;
case 1:
return EnumValue2;
}
return null;
}
}
MyEnum.values()[x]
是一个昂贵的操作吗?我不知道它的详细工作原理,但对我来说,似乎访问数组中的元素并不是什么大问题,即常数时间。如果需要构建数组,则需要O(n)时间,这与您的解决方案具有相同的运行时间。 - brunsgaardvalues()
每次都会生成一个新的数组,因为数组是可变的,所以多次返回同一个数组可能不安全。switch语句不一定是O(n),它们可以被编译成跳转表。所以Lorenzo的说法似乎是有道理的。 - MikeFHaymyEnum = myEnumValues[i]
仍将返回枚举中的第i
项,而无需更改。 - Dandre Allison如果你想给整数赋值,可以使用以下结构
public enum A
{
B(0),
C(10),
None(11);
int id;
private A(int i){id = i;}
public int GetID(){return id;}
public boolean IsEmpty(){return this.equals(A.None);}
public boolean Compare(int i){return id == i;}
public static A GetValue(int _id)
{
A[] As = A.values();
for(int i = 0; i < As.length; i++)
{
if(As[i].Compare(_id))
return As[i];
}
return A.None;
}
}
A.values()[ some_id ];
,当你传递11
时,它当然不会返回None
。 - 463035818_is_not_a_number您可以尝试这样做。
创建具有元素id的类。
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public static MyEnum fromId(int id) {
for (MyEnum type : values()) {
if (type.getId() == id) {
return type;
}
}
return null;
}
}
现在使用整数id获取此枚举。
MyEnum myEnum = MyEnum.fromId(5);
我缓存这些值并创建了一个简单的静态访问方法:
public static enum EnumAttributeType {
ENUM_1,
ENUM_2;
private static EnumAttributeType[] values = null;
public static EnumAttributeType fromInt(int i) {
if(EnumAttributeType.values == null) {
EnumAttributeType.values = EnumAttributeType.values();
}
return EnumAttributeType.values[i];
}
}
this.values()
会导致-_java.lang.NullPointerException: Cannot invoke "[LFooBar;.clone()" because "FooBar.$VALUES" is null_。 - mnscfromOrdinal(int)
可能是一个更好的名称,因为有很多替代方案,比如 @Doctor 在这里提供的使用合成/显式 int 值的答案,比如 id
或 value
。 - mnscJava枚举类型没有像C++中那样的枚举到整数映射。
话虽如此,所有的枚举类型都有一个values
方法,用于返回可能的枚举值数组,因此
MyEnum enumValue = MyEnum.values()[x];
应该可以工作。虽然有点糟糕,但如果可能的话最好不要尝试将int
转换为Enum
(反之亦然)。
这并不是通常做的事情,所以我建议您重新考虑。但是话说回来,基本操作是:使用EnumType.values()[intNum]
将int转为枚举,使用enumInst.ordinal()
将枚举转为int。
然而,由于任何values()
方法的实现都只会给你一个数组的副本(Java 数组永远不会是只读的),因此最好使用EnumMap
来缓存枚举--> int 映射。
Use MyEnum enumValue = MyEnum.values()[x];
这是我打算采用的解决方案。它不仅适用于非连续的整数,而且对于您可能想要作为枚举值底层id使用的任何其他数据类型都应该适用。
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public static Map<Integer, MyEnum> buildMap() {
Map<Integer, MyEnum> map = new HashMap<Integer, MyEnum>();
MyEnum[] values = MyEnum.values();
for (MyEnum value : values) {
map.put(value.getId(), value);
}
return map;
}
}
我只需要在特定时间(从文件加载数据时)将id转换为枚举,所以没有必要一直在内存中保留Map。如果您确实需要随时访问该映射表,则可以将其缓存为Enum类的静态成员。
clearCachedValues
(将私有字段设置回null)。我认为MyEnum.fromInt(i)
比传递映射对象更容易理解。 - ToolmakerSteve如果能够帮助其他人,我推荐的选项没有在这里列出,它使用了Guava的Maps功能:
public enum MyEnum {
OPTION_1(-66),
OPTION_2(32);
private int value;
private MyEnum(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
private static ImmutableMap<Integer, MyEnum> reverseLookup =
Maps.uniqueIndex(Arrays.asList(MyEnum.values())), MyEnum::getValue);
public static MyEnum fromInt(final int id) {
return reverseLookup.getOrDefault(id, OPTION_1);
}
}
默认情况下,您可以使用 null
,也可以 throw IllegalArgumentException
或者您的 fromInt
可以返回一个 Optional
,无论您喜欢哪种行为。
Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
- shmoselgetValue()
方法。 - shmosel
MyEnum.values()
,可以将其缓存起来以节省开销。即使这个操作很耗时。 - Peter Lawrey