在Java中转换为enum。

时间:2023-01-26 14:24:04

What is the correct way to cast an Int to an enum in Java given the following enum?

在下面的枚举中,将Int类型转换为枚举的正确方法是什么?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


MyEnum enumValue = (MyEnum) x; //Doesn't work???

15 个解决方案

#1


513  

Try MyEnum.values()[x] where x must be 0 or 1, i.e. a valid ordinal for that enum.

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

Note that in Java enums actually are classes (and enum values thus are objects) and thus you can't cast an int or even Integer to an enum.

注意,在Java枚举中实际上是类(enum值因此是对象),因此不能将int甚至整型赋值给enum。

#2


142  

MyEnum.values()[x] is an expensive operation. If the performance is a concern, you may want to do something like this:

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

#3


41  

If you want to give your integer values, you can use a structure like below

如果想要给出整数值,可以使用如下结构

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

#4


21  

You can try like this.
Create Class with element id.

你可以这样试试。使用元素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;
            }
      }

Now Fetch this Enum using id as int.

现在使用id作为int获取这个Enum。

MyEnum myEnum = MyEnum.fromId(5);

#5


19  

I cache the values and create a simple static access method:

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

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

#6


9  

Java enums don't have the same kind of enum-to-int mapping that they do in C++.

Java enums没有与c++中相同的枚举到int映射。

That said, all enums have a values method that returns an array of possible enum values, so

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

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

should work. It's a little nasty and it might be better to not try and convert from ints to Enums (or vice versa) if possible.

应该工作。这有点麻烦,如果可能的话,最好不要尝试将ints转换为Enums(反之亦然)。

#7


9  

This not something that is usually done, so I would reconsider. But having said that, the fundamental operations are: int --> enum using EnumType.values()[intNum], and enum --> int using enumInst.ordinal().

这不是通常的事情,所以我会重新考虑。但是,说到这一点,基本操作是:int—>枚举使用EnumType.values()[intNum]和enum——> int使用en. ordinal()。

However, since any implementation of values() has no choice but to give you a copy of the array (java arrays are never read-only), you would be better served using an EnumMap to cache the enum --> int mapping.

但是,由于任何值()实现都别无选择,只能提供数组的副本(java数组从来不是只读的),因此最好使用枚举映射缓存enum -> int映射。

#8


7  

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

使用MyEnum枚举值= MyEnum.values()[x];

#9


6  

Here's the solution I plan to go with. Not only does this work with non-sequential integers, but it should work with any other data type you may want to use as the underlying id for your enum values.

这是我计划要解决的问题。这不仅与非顺序整数一起工作,而且它应该与您可能想要用作枚举值的底层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;
    }
}

I only need to convert id's to enums at specific times (when loading data from a file), so there's no reason for me to keep the Map in memory at all times. If you do need the map to be accessible at all times, you can always cache it as a static member of your Enum class.

我只需要在特定的时间(从文件加载数据时)将id转换为枚举,所以我没有理由一直将映射保存在内存中。如果您确实需要在任何时候都可以访问映射,那么您总是可以将其缓存为Enum类的静态成员。

#10


3  

In case it helps others, the option I prefer, which is not listed here, uses Guava's Maps functionality:

为了帮助其他人,我喜欢的选项(这里没有列出)使用了番石榴的地图功能:

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

With the default you can use null, you can throw IllegalArgumentException or your fromInt could return an Optional, whatever behavior you prefer.

默认情况下,您可以使用null,可以抛出IllegalArgumentException,或者您的fromInt可以返回一个可选的、您喜欢的任何行为。

#11


2  

You can iterate over values() of enum and compare integer value of enum with given id like below:

您可以对enum的值()进行迭代,并将enum的整数值与给定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
    }
}

And use just like this:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
I hope this helps ;)

并使用如下所示:TestEnum x = TestEnum.getEnum(4);//将返回TestEnum。我希望这能有所帮助;

#12


0  

A good option is to avoid conversion from int to enum: for example, if you need the maximal value, you may compare x.ordinal() to y.ordinal() and return x or y correspondingly. (You may need to re-order you values to make such comparison meaningful.)

一个好的选择是避免从int到enum的转换:例如,如果需要最大值,可以将x.ordinal()与y.序al()进行比较,然后相应地返回x或y。(您可能需要重新排序您的值,以使这种比较有意义。)

If that is not possible, I would store MyEnum.values() into a static array.

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

#13


0  

This is the same answer as the doctors but it shows how to eliminate the problem with mutable arrays. If you use this kind of approach because of branch prediction first if will have very little to zero effect and whole code only calls mutable array values() function only once. As both variables are static they will not consume n * memory for every usage of this enumeration too.

这与医生的答案相同,但它显示了如何消除可变数组的问题。如果您使用这种方法,因为分支预测首先会有非常小的影响,而整个代码只调用可变数组值()函数一次。由于这两个变量都是静态的,所以它们也不会占用这个枚举的每个用法的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;
}

#14


0  

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

#15


0  

This should address the indexes getting out of sync with the ordinal value issue.

这应该可以解决索引与序数值问题不同步的问题。

package service.manager;

public enum Command {
    PRINT_FOO(0),
    PRINT_BAR(2),
    PRINT_BAZ(3);

    public int intVal;
    Command(int intVal){
        this.intVal = intVal;
    }

    /**
     * Functionality to ascertain an enum from an int
     * The static block initializes the array indexes to correspond with it's according ordinal value
     * Simply use Command.values[index] or get the int value by e.g. Command.PRINT_FOO.intVal;
     * */
    public static Command values[];
    static{
        int maxVal = -1;
        for(Command cmd : Command.values())
            if(maxVal < cmd.intVal)
                maxVal = cmd.intVal;

        values = new Command[maxVal + 1];

        for(Command cmd : Command.values())
            values[cmd.intVal] = cmd;
    }
}

#1


513  

Try MyEnum.values()[x] where x must be 0 or 1, i.e. a valid ordinal for that enum.

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

Note that in Java enums actually are classes (and enum values thus are objects) and thus you can't cast an int or even Integer to an enum.

注意,在Java枚举中实际上是类(enum值因此是对象),因此不能将int甚至整型赋值给enum。

#2


142  

MyEnum.values()[x] is an expensive operation. If the performance is a concern, you may want to do something like this:

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

#3


41  

If you want to give your integer values, you can use a structure like below

如果想要给出整数值,可以使用如下结构

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

#4


21  

You can try like this.
Create Class with element id.

你可以这样试试。使用元素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;
            }
      }

Now Fetch this Enum using id as int.

现在使用id作为int获取这个Enum。

MyEnum myEnum = MyEnum.fromId(5);

#5


19  

I cache the values and create a simple static access method:

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

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

#6


9  

Java enums don't have the same kind of enum-to-int mapping that they do in C++.

Java enums没有与c++中相同的枚举到int映射。

That said, all enums have a values method that returns an array of possible enum values, so

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

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

should work. It's a little nasty and it might be better to not try and convert from ints to Enums (or vice versa) if possible.

应该工作。这有点麻烦,如果可能的话,最好不要尝试将ints转换为Enums(反之亦然)。

#7


9  

This not something that is usually done, so I would reconsider. But having said that, the fundamental operations are: int --> enum using EnumType.values()[intNum], and enum --> int using enumInst.ordinal().

这不是通常的事情,所以我会重新考虑。但是,说到这一点,基本操作是:int—>枚举使用EnumType.values()[intNum]和enum——> int使用en. ordinal()。

However, since any implementation of values() has no choice but to give you a copy of the array (java arrays are never read-only), you would be better served using an EnumMap to cache the enum --> int mapping.

但是,由于任何值()实现都别无选择,只能提供数组的副本(java数组从来不是只读的),因此最好使用枚举映射缓存enum -> int映射。

#8


7  

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

使用MyEnum枚举值= MyEnum.values()[x];

#9


6  

Here's the solution I plan to go with. Not only does this work with non-sequential integers, but it should work with any other data type you may want to use as the underlying id for your enum values.

这是我计划要解决的问题。这不仅与非顺序整数一起工作,而且它应该与您可能想要用作枚举值的底层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;
    }
}

I only need to convert id's to enums at specific times (when loading data from a file), so there's no reason for me to keep the Map in memory at all times. If you do need the map to be accessible at all times, you can always cache it as a static member of your Enum class.

我只需要在特定的时间(从文件加载数据时)将id转换为枚举,所以我没有理由一直将映射保存在内存中。如果您确实需要在任何时候都可以访问映射,那么您总是可以将其缓存为Enum类的静态成员。

#10


3  

In case it helps others, the option I prefer, which is not listed here, uses Guava's Maps functionality:

为了帮助其他人,我喜欢的选项(这里没有列出)使用了番石榴的地图功能:

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

With the default you can use null, you can throw IllegalArgumentException or your fromInt could return an Optional, whatever behavior you prefer.

默认情况下,您可以使用null,可以抛出IllegalArgumentException,或者您的fromInt可以返回一个可选的、您喜欢的任何行为。

#11


2  

You can iterate over values() of enum and compare integer value of enum with given id like below:

您可以对enum的值()进行迭代,并将enum的整数值与给定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
    }
}

And use just like this:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
I hope this helps ;)

并使用如下所示:TestEnum x = TestEnum.getEnum(4);//将返回TestEnum。我希望这能有所帮助;

#12


0  

A good option is to avoid conversion from int to enum: for example, if you need the maximal value, you may compare x.ordinal() to y.ordinal() and return x or y correspondingly. (You may need to re-order you values to make such comparison meaningful.)

一个好的选择是避免从int到enum的转换:例如,如果需要最大值,可以将x.ordinal()与y.序al()进行比较,然后相应地返回x或y。(您可能需要重新排序您的值,以使这种比较有意义。)

If that is not possible, I would store MyEnum.values() into a static array.

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

#13


0  

This is the same answer as the doctors but it shows how to eliminate the problem with mutable arrays. If you use this kind of approach because of branch prediction first if will have very little to zero effect and whole code only calls mutable array values() function only once. As both variables are static they will not consume n * memory for every usage of this enumeration too.

这与医生的答案相同,但它显示了如何消除可变数组的问题。如果您使用这种方法,因为分支预测首先会有非常小的影响,而整个代码只调用可变数组值()函数一次。由于这两个变量都是静态的,所以它们也不会占用这个枚举的每个用法的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;
}

#14


0  

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

#15


0  

This should address the indexes getting out of sync with the ordinal value issue.

这应该可以解决索引与序数值问题不同步的问题。

package service.manager;

public enum Command {
    PRINT_FOO(0),
    PRINT_BAR(2),
    PRINT_BAZ(3);

    public int intVal;
    Command(int intVal){
        this.intVal = intVal;
    }

    /**
     * Functionality to ascertain an enum from an int
     * The static block initializes the array indexes to correspond with it's according ordinal value
     * Simply use Command.values[index] or get the int value by e.g. Command.PRINT_FOO.intVal;
     * */
    public static Command values[];
    static{
        int maxVal = -1;
        for(Command cmd : Command.values())
            if(maxVal < cmd.intVal)
                maxVal = cmd.intVal;

        values = new Command[maxVal + 1];

        for(Command cmd : Command.values())
            values[cmd.intVal] = cmd;
    }
}