Cast Int à enum en Java
Quelle est la bonne façon de lancer un Int dans un enum en Java étant donné l'enum suivant?
public enum MyEnum
{
EnumValue1,
EnumValue2
}
MyEnum enumValue = (MyEnum) x; //Doesn't work???
15 réponses
Essayer MyEnum.values()[x]
où x
doit être 0
ou 1
, c'est à dire valable ordinal qui enum.
notez qu'en Java les enums sont en fait des classes (et les valeurs d'enum sont donc des objets) et donc vous ne pouvez pas lancer un int
ou même Integer
sur un enum.
MyEnum.values()[x]
est une opération coûteuse. Si la performance est un problème, vous pouvez faire quelque chose comme ceci:
public enum MyEnum {
EnumValue1,
EnumValue2;
public static MyEnum fromInteger(int x) {
switch(x) {
case 0:
return EnumValue1;
case 1:
return EnumValue2;
}
return null;
}
}
si vous voulez donner vos valeurs entières, vous pouvez utiliser une structure comme ci-dessous
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;
}
}
Vous pouvez essayer comme ça.
Créer une Classe avec id d'élément.
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;
}
}
maintenant, récupérez cet Enum en utilisant id comme int.
MyEnum myEnum = MyEnum.fromId(5);
je cache les valeurs et crée une méthode d'accès statique simple:
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];
}
}
Java enums n'ont pas le même genre de cartographie enum-to-int qu'ils font en C++.
cela dit, tous les enums ont une méthode values
qui retourne un tableau de valeurs possibles d'enum, donc
MyEnum enumValue = MyEnum.values()[x];
devrait marcher. Il est un peu désagréable et il pourrait être préférable de ne pas essayer de convertir de int
s à Enum
s (ou vice versa) si possible.
Ce n'est pas quelque chose qui est habituellement fait, donc je revienne. Mais cela dit, les opérations fondamentales sont: int --> enum en utilisant EnumType.les valeurs de()[intNum], et enum --> int utilisant enumInst.ordinal.)(
cependant, étant donné que n'importe quelle implémentation de values() n'a pas d'autre choix que de vous donner une copie du tableau (les tableaux java ne sont jamais en lecture seule), vous seriez mieux servi en utilisant un EnumMap pour mettre en cache la cartographie enum --> int.
Voici la solution que je prévois d'adopter. Non seulement cela fonctionne avec des entiers non séquentiels, mais cela devrait fonctionner avec tout autre type de données que vous pourriez vouloir utiliser comme id sous-jacent pour vos valeurs enum.
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;
}
}
j'ai seulement besoin de convertir les id en enums à des moments précis (lors du chargement de données à partir d'un fichier), donc il n'y a aucune raison pour moi de garder la carte en mémoire à tout moment. Si vous avez besoin que la carte soit accessible en tout temps, vous pouvez toujours la mettre en cache membre statique de votre classe D'Enum.
dans le cas où il aide les autres, l'option que je préfère, qui n'est pas énumérée ici, utilise la fonctionnalité de cartes de goyave :
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);
}
}
avec la valeur par défaut vous pouvez utiliser null
, vous pouvez throw IllegalArgumentException
ou votre fromInt
pourrait retourner un Optional
, quel que soit le comportement que vous préférez.
vous pouvez itérer sur values()
de l'enum et comparer la valeur entière de l'enum avec donnée id
comme ci-dessous:
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
}
}
et utilisez comme ceci:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
J'espère que cette aide ;)
une bonne option est de éviter conversion de int
à enum
: par exemple, si vous avez besoin de la valeur maximale, vous pouvez comparer X. ordinal () to Y. ordinal () and return x or y correspondingly. (Vous aurez peut-être besoin de réorganiser vos valeurs pour rendre une telle comparaison significative.)
si cela n'est pas possible, je stockerais MyEnum.values()
dans un tableau statique.
C'est la même réponse que les médecins mais elle montre comment éliminer le problème avec les matrices mutables. Si vous utilisez ce genre d'approche à cause de la prédiction de branche d'abord si aura très peu à effet zéro et le code entier appelle seulement les valeurs de tableau mutable() la fonction seulement une fois. Comme les deux variables sont statiques, elles ne consommeront pas n * memory pour chaque utilisation de cette énumération.
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;
}
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;
}
}
}
ceci devrait s'appliquer aux index qui ne sont pas synchronisés avec la question de la valeur ordinale.
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;
}
}