在Java中将Int转换为enum

在Java中给定以下enum,将Int类型转换为enum的正确方法是什么?

public enum MyEnum
{
EnumValue1,
EnumValue2
}




MyEnum enumValue = (MyEnum) x; //Doesn't work???
327468 次浏览

尝试MyEnum.values()[x],其中x必须为01,即该枚举的有效序数。

注意,在Java中枚举实际上是类(enum值因此是对象),因此你不能将int甚至Integer强制转换为enum。

使用MyEnum enumValue = MyEnum.values()[x];

Java枚举没有c++中那样的枚举到int的映射。

也就是说,所有枚举都有一个values方法,该方法返回可能的枚举值数组,因此

MyEnum enumValue = MyEnum.values()[x];

应该工作。这有点讨厌,如果可能的话,最好不要尝试从__abc0转换为__abc1(反之亦然)。

这不是通常做的事情,所以我会重新考虑。但话虽如此,基本操作是:int—>使用EnumType.values()[intNum]和enum——>int使用enumInst.ordinal()

然而,由于values()的任何实现都只能给你一个数组的副本(java数组从来不是只读的),所以你最好使用EnumMap来缓存枚举——>int映射。

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;
}
}

一个很好的选择是从intenum避免转换:例如,如果你需要最大值,你可以比较x.o ordinal()和y.o ordinal()并相应地返回x或y。(您可能需要重新排序您的值,使这样的比较有意义。)

如果不可能,我会将MyEnum.values()存储到一个静态数组中。

我缓存这些值并创建一个简单的静态访问方法:

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];
}
}

如果你想给你的整数值,你可以使用如下结构

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;
}
}

这与医生给出的答案相同,但它展示了如何用可变数组消除问题。如果你使用这种方法,因为分支预测,如果将有非常小的影响到零,整个代码只调用可变数组values()函数只有一次。因为这两个变量都是静态的,所以每次使用这个枚举也不会消耗n *内存。

private static boolean arrayCreated = false;
private static RFMsgType[] ArrayOfValues;


public static RFMsgType GetMsgTypeFromValue(int MessageID) {
if (arrayCreated == false) {
ArrayOfValues = RFMsgType.values();
}


for (int i = 0; i < ArrayOfValues.length; i++) {
if (ArrayOfValues[i].MessageIDValue == MessageID) {
return ArrayOfValues[i];
}
}
return RFMsgType.UNKNOWN;
}

这是我打算采用的解决方案。这不仅适用于非连续整数,而且适用于您可能希望用作枚举值的底层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转换为enum,所以我没有理由一直将Map保存在内存中。如果您确实需要在任何时候都可以访问映射,那么您总是可以将它缓存为Enum类的静态成员。

你可以这样试试 用元素id创建Class。< / p >

      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作为int来获取这个Enum

MyEnum myEnum = MyEnum.fromId(5);
enum MyEnum {
A(0),
B(1);
private final int value;
private MyEnum(int val) {this.value = value;}
private static final MyEnum[] values = MyEnum.values();//cache for optimization
public static final getMyEnum(int value) {
try {
return values[value];//OOB might get triggered
} catch (ArrayOutOfBoundsException e) {
} finally {
return myDefaultEnumValue;
}
}
}

写了这个实现。它允许缺失值、负值并保持代码的一致性。映射也会被缓存。使用接口,需要Java 8。

枚举

public enum Command implements OrdinalEnum{
PRINT_FOO(-7),
PRINT_BAR(6),
PRINT_BAZ(4);


private int val;
private Command(int val){
this.val = val;
}


public int getVal(){
return val;
}


private static Map<Integer, Command> map = OrdinalEnum.getValues(Command.class);
public static Command from(int i){
return map.get(i);
}
}

接口

public interface OrdinalEnum{
public int getVal();


@SuppressWarnings("unchecked")
static <E extends Enum<E>> Map<Integer, E> getValues(Class<E> clzz){
Map<Integer, E> m = new HashMap<>();
for(Enum<E> e : EnumSet.allOf(clzz))
m.put(((OrdinalEnum)e).getVal(), (E)e);


return m;
}
}

你可以遍历枚举的values(),并将枚举的整数值与给定的id进行比较,如下所示:

public enum  TestEnum {
None(0),
Value1(1),
Value2(2),
Value3(3),
Value4(4),
Value5(5);


private final int value;
private TestEnum(int value) {
this.value = value;
}


public int getValue() {
return value;
}


public static TestEnum  getEnum(int value){
for (TestEnum e:TestEnum.values()) {
if(e.getValue() == value)
return e;
}
return TestEnum.None;//For values out of enum scope
}
}
然后像这样使用:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
我希望这对你有所帮助;)

为了帮助其他人,我更喜欢的选项,这里没有列出,使用Guava的地图功能:

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,任何你喜欢的行为。

根据@ChadBefus的回答和@shmosel的评论,我建议使用这个。(高效查找,工作在纯java >= 8)

import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Map;
import java.util.Arrays;


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 Map<Integer, MyEnum> reverseLookup =
Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));


public static MyEnum fromInt(final int id) {
return reverseLookup.getOrDefault(id, OPTION_1);
}
public static void main(String[] args) {
System.out.println(fromInt(-66).toString());
}
}

在芬兰湾的科特林:

enum class Status(val id: Int) {
NEW(0), VISIT(1), IN_WORK(2), FINISHED(3), CANCELLED(4), DUMMY(5);


companion object {
private val statuses = Status.values().associateBy(Status::id)


fun getStatus(id: Int): Status? = statuses[id]
}
}

用法:

val status = Status.getStatus(1)!!