Eu tenho um enum como este:
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;
}
}
Agora eu obtenho um int de uma entrada externa e quero a entrada correspondente - lançar uma exceção se um valor não existir está ok, mas de preferência, seria DLT_UNKNOWN
nesse caso.
int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */
EnumMap
usa os enums como chaves. Nesse caso, o OP deseja os enums como os valores.values()
(se seus valores enum forem sequenciais) ou umaswitch
instrução simples venceria este método facilmente . Se você tiver apenas um punhado de entradas em seuEnum
, não faz muito sentido adicionar a sobrecarga de um HashMap simplesmente para a conveniência de não ter que atualizar aswitch
instrução. Esse método pode parecer mais elegante, mas também é um desperdício.Existe um método estático
values()
que está documentado, mas não onde você esperava: 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];} }
Em princípio, você pode usar just
values()[i]
, mas há rumores de quevalues()
criarão uma cópia do array cada vez que for invocado.fonte
Você terá que criar um novo método estático em que itera PcapLinkType.values () e compare:
public static PcapLinkType forCode(int code) { for (PcapLinkType typе : PcapLinkType.values()) { if (type.getValue() == code) { return type; } } return null; }
Isso seria ótimo se raramente fosse chamado. Se for chamado com frequência, observe a
Map
otimização sugerida por outros.fonte
Você pode fazer algo assim para registrá-los automaticamente em uma coleção com a qual converter facilmente os inteiros para o enum correspondente. (Aliás, adicioná-los ao mapa no construtor enum não é permitido . É bom aprender coisas novas mesmo depois de muitos anos usando 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); } }
fonte
se você tem enum como este
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; } }
então você pode usá-lo como
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
fonte
Como @MeBigFatGuy diz, exceto que você pode fazer seu
static {...}
bloco usar um loop sobre avalues()
coleção:static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.getValue(), type); } }
fonte
Sei que essa pergunta já existe há alguns anos, mas como o Java 8, entretanto, nos trouxe
Optional
, pensei em oferecer uma solução usando ele (eStream
eCollectors
):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
é comonull
: representa um caso em que não há valor (válido). Mas é uma alternativa mais segura para o tiponull
ou um valor padrão, comoDLT_UNKNOWN
porque você pode esquecer de verificar os casosnull
ouDLT_UNKNOWN
. Ambos sãoPcapLinkType
valores válidos ! Em contraste, você não pode atribuir umOptional<PcapLinkType>
valor a uma variável do tipoPcapLinkType
.Optional
faz com que você verifique um valor válido primeiro.Claro, se você quiser manter
DLT_UNKNOWN
para compatibilidade com versões anteriores ou qualquer outro motivo, você ainda pode usar,Optional
mesmo nesse caso, usandoorElse()
para especificá-lo como o valor padrão: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); } }
fonte
Você pode adicionar um método estático em seu enum que aceite um
int
como um parâmetro e retorne umPcapLinkType
.public static PcapLinkType of(int linkType) { switch (linkType) { case -1: return DLT_UNKNOWN case 0: return DLT_NULL; //ETC.... default: return null; } }
fonte
switch
instrução se você adicionar um novo enum. Não é o ideal, IMHO.Isso é o que eu 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); } }
fonte
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; } }
fonte
.values()
método?).--int
, mas é obviamente um erro de digitação.null
no lugar deDLT_UKNOWN
:)static final values[] = PcapLinkType.values()
?Não há como manipular elegantemente tipos enumerados baseados em inteiros. Você pode pensar em usar uma enumeração baseada em string em vez de sua solução. Não é uma forma preferida todas as vezes, mas ainda 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); } }
fonte