J’ai un enum comme ça:
public enum PcapLinkType { DLT_NULL(0) DLT_EN10MB(1) DLT_EN3MB(2), DLT_AX25(3), /*snip, 200 more enums, not always consecutive.*/ DLT_UNKNOWN(-1); private final int value; PcapLinkType(int value) { this.value= value; } }
Maintenant, j’obtiens un int depuis l’entrée externe et je veux l’entrée correspondante – lancer une exception si une valeur n’existe pas est acceptable, mais je préférerais que ce soit DLT_UNKNOWN
dans ce cas.
int val = in.readInt(); PcapLinkType type = ???; /*convert val to a PcapLinkType */
Vous devrez le faire manuellement en ajoutant une carte statique dans la classe qui mappe les entiers aux énumérations, telles que
private static final Map intToTypeMap = new HashMap(); static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.value, type); } } public static PcapLinkType fromInt(int i) { PcapLinkType type = intToTypeMap.get(Integer.valueOf(i)); if (type == null) return PcapLinkType.DLT_UNKNOWN; return type; }
Il y a une méthode statique values()
qui est documentée, mais pas où vous vous y attendriez: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
enum MyEnum { FIRST, SECOND, THIRD; private static MyEnum[] allValues = values(); public static MyEnum fromOrdinal(int n) {return allValues[n];} }
En principe, vous ne pouvez utiliser que des values()[i]
, mais il y a des rumeurs selon lesquelles des values()
créeront une copie du tableau à chaque appel.
Vous devrez créer une nouvelle méthode statique pour itérer PcapLinkType.values () et comparer:
public static PcapLinkType forCode(int code) { for (PcapLinkType typе : PcapLinkType.values()) { if (type.getValue() == code) { return type; } } return null; }
Ce serait bien si on l’appelle rarement. Si elle est appelée fréquemment, consultez l’optimisation de Map
proposée par d’autres utilisateurs.
si tu as enum comme ça
public enum PcapLinkType { DLT_NULL(0) DLT_EN10MB(1) DLT_EN3MB(2), DLT_AX25(3), DLT_UNKNOWN(-1); private final int value; PcapLinkType(int value) { this.value= value; } }
alors vous pouvez l’utiliser comme
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
Vous pouvez faire quelque chose comme ça pour les enregistrer automatiquement dans une collection avec laquelle convertir facilement les entiers en enum correspondant. (BTW, les append à la carte dans le constructeur enum n’est pas autorisé . C’est bien d’apprendre de nouvelles choses même après plusieurs années d’utilisation de Java. 🙂
public enum PcapLinkType { DLT_NULL(0), DLT_EN10MB(1), DLT_EN3MB(2), DLT_AX25(3), /*snip, 200 more enums, not always consecutive.*/ DLT_UNKNOWN(-1); private static final Map typesByValue = new HashMap(); static { for (PcapLinkType type : PcapLinkType.values()) { typesByValue.put(type.value, type); } } private final int value; private PcapLinkType(int value) { this.value = value; } public static PcapLinkType forValue(int value) { return typesByValue.get(value); } }
Comme @MeBigFatGuy le dit, sauf que vous pouvez faire en sorte que votre bloc static {...}
utilise une boucle sur la collection values()
:
static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.getValue(), type); } }
Je sais que cette question a quelques années, mais comme Java 8 nous a apporté, en attendant, une Optional
, j’ai pensé proposer une solution (et Stream
et Collectors
):
public enum PcapLinkType { DLT_NULL(0), DLT_EN3MB(2), DLT_AX25(3), /*snip, 200 more enums, not always consecutive.*/ // DLT_UNKNOWN(-1); // <--- NO LONGER NEEDED private final int value; private PcapLinkType(int value) { this.value = value; } private static final Map map; static { map = Arrays.stream(values()) .collect(Collectors.toMap(e -> e.value, e -> e)); } public static Optional fromInt(int value) { return Optional.ofNullable(map.get(value)); } }
Optional
est comme null
: il représente un cas où il n’y a pas de valeur (valide). Mais c’est une alternative plus sûre à null
ou une valeur par défaut telle que DLT_UNKNOWN
car vous pourriez oublier de vérifier les cas null
ou DLT_UNKNOWN
. Ce sont deux valeurs PcapLinkType
valides! En revanche, vous ne pouvez pas affecter une valeur Optional
à une variable de type PcapLinkType
. Optional
vous vérifiez d’abord une valeur valide.
Bien sûr, si vous souhaitez conserver DLT_UNKNOWN
pour la compatibilité descendante ou pour toute autre raison, vous pouvez toujours utiliser la fonctionnalité Optional
dans ce cas, en utilisant orElse()
pour le spécifier comme valeur par défaut:
public enum PcapLinkType { DLT_NULL(0), DLT_EN3MB(2), DLT_AX25(3), /*snip, 200 more enums, not always consecutive.*/ DLT_UNKNOWN(-1); private final int value; private PcapLinkType(int value) { this.value = value; } private static final Map map; static { map = Arrays.stream(values()) .collect(Collectors.toMap(e -> e.value, e -> e)); } public static PcapLinkType fromInt(int value) { return Optional.ofNullable(map.get(value)).orElse(DLT_UNKNOWN); } }
Vous pouvez append une méthode statique dans votre enum qui accepte un int
comme paramètre et renvoie un PcapLinkType
.
public static PcapLinkType of(int linkType) { switch (linkType) { case -1: return DLT_UNKNOWN case 0: return DLT_NULL; //ETC.... default: return null; } }
C’est ce que j’utilise:
public enum Quality {ENOUGH,BETTER,BEST; private static final int amount = EnumSet.allOf(Quality.class).size(); private static Quality[] val = new Quality[amount]; static{ for(Quality q:EnumSet.allOf(Quality.class)){ val[q.ordinal()]=q; } } public static Quality fromInt(int i) { return val[i]; } public Quality next() { return fromInt((ordinal()+1)%amount); } }
static final PcapLinkType[] values = { DLT_NULL, DLT_EN10MB, DLT_EN3MB, null ...} ... public static PcapLinkType getPcapLinkTypeForInt(int num){ try{ return values[int]; }catch(ArrayIndexOutOfBoundsException e){ return DLT_UKNOWN; } }