Tengo una enumeración como esta:
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;
}
}
Ahora obtengo un int de la entrada externa y quiero la entrada coincidente: lanzar una excepción si un valor no existe está bien, pero preferiblemente lo haría DLT_UNKNOWN
en ese caso.
int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */
EnumMap
usa las enumeraciones como claves. En este caso, el OP quiere las enumeraciones como valores.values()
(si sus valores de enumeración son secuenciales) o unaswitch
declaración simple superaría este método fácilmente . Si solo tiene un puñado de entradas en su,Enum
entonces no tiene mucho sentido agregar la sobrecarga de un HashMap simplemente por la conveniencia de no tener que actualizar laswitch
declaración. Este método puede parecer más elegante, pero también es un desperdicio.Hay un método estático
values()
que está documentado, pero no donde lo esperaría: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.htmlenum MyEnum { FIRST, SECOND, THIRD; private static MyEnum[] allValues = values(); public static MyEnum fromOrdinal(int n) {return allValues[n];} }
En principio, puede usar solo
values()[i]
, pero hay rumores quevalues()
crearán una copia de la matriz cada vez que se invoque.fuente
Tendrás que crear un nuevo método estático en el que iterarás PcapLinkType.values () y compararás:
public static PcapLinkType forCode(int code) { for (PcapLinkType typе : PcapLinkType.values()) { if (type.getValue() == code) { return type; } } return null; }
Eso estaría bien si se llama raramente. Si se llama con frecuencia, observe la
Map
optimización sugerida por otros.fuente
Puede hacer algo como esto para registrarlos todos automáticamente en una colección con la que luego convertir fácilmente los enteros en la enumeración correspondiente. (Por cierto, no se permite agregarlos al mapa en el constructor de enumeración . Es bueno aprender cosas nuevas incluso después de muchos años de usar 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<Integer, PcapLinkType> typesByValue = new HashMap<Integer, PcapLinkType>(); 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); } }
fuente
si tienes una enumeración como esta
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; } }
entonces puedes usarlo como
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
fuente
Como dice @MeBigFatGuy, excepto que puede hacer que su
static {...}
bloque use un bucle sobre lavalues()
colección:static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.getValue(), type); } }
fuente
Sé que esta pregunta tiene algunos años, pero como Java 8, mientras tanto, nos trajo
Optional
, pensé en ofrecer una solución usándola (yStream
yCollectors
):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<Integer, PcapLinkType> map; static { map = Arrays.stream(values()) .collect(Collectors.toMap(e -> e.value, e -> e)); } public static Optional<PcapLinkType> fromInt(int value) { return Optional.ofNullable(map.get(value)); } }
Optional
es comonull
: representa un caso en el que no hay ningún valor (válido). Pero es una alternativa más segura para los tiposnull
o un valor predeterminado, por ejemplo,DLT_UNKNOWN
porque podría olvidarse de verificar los casosnull
oDLT_UNKNOWN
. ¡Ambos sonPcapLinkType
valores válidos ! Por el contrario, no puede asignar unOptional<PcapLinkType>
valor a una variable de tipoPcapLinkType
.Optional
le hace comprobar primero un valor válido.Por supuesto, si desea conservar
DLT_UNKNOWN
para compatibilidad con versiones anteriores o cualquier otra razón, aún puede usarOptional
incluso en ese caso, usandoorElse()
para especificarlo como el valor predeterminado: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<Integer, PcapLinkType> 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); } }
fuente
Puede agregar un método estático en su enumeración que acepte un
int
como parámetro y devuelva unPcapLinkType
.public static PcapLinkType of(int linkType) { switch (linkType) { case -1: return DLT_UNKNOWN case 0: return DLT_NULL; //ETC.... default: return null; } }
fuente
switch
declaración si agrega una nueva enumeración. No es ideal, en mi humilde opinión.Esto es lo que uso:
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); } }
fuente
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; } }
fuente
.values()
método?).--int
, pero obviamente es un error tipográfico.null
en lugar deDLT_UKNOWN
:)static final values[] = PcapLinkType.values()
?No hay forma de manejar con elegancia los tipos enumerados basados en números enteros. Podría pensar en usar una enumeración basada en cadenas en lugar de su solución. No es una forma preferida todas las veces, pero aún existe.
public enum Port { /** * The default port for the push server. */ DEFAULT("443"), /** * The alternative port that can be used to bypass firewall checks * made to the default <i>HTTPS</i> port. */ ALTERNATIVE("2197"); private final String portString; Port(final String portString) { this.portString = portString; } /** * Returns the port for given {@link Port} enumeration value. * @return The port of the push server host. */ public Integer toInteger() { return Integer.parseInt(portString); } }
fuente