Mam takie wyliczenie:
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;
}
}
Teraz otrzymuję int z zewnętrznego wejścia i chcę dopasować dane wejściowe - zgłoszenie wyjątku, jeśli wartość nie istnieje, jest w porządku, ale najlepiej byłoby, gdyby tak było DLT_UNKNOWN
.
int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */
EnumMap
używa wyliczeń jako kluczy. W tym przypadku OP chce wyliczeń jako wartości.values()
(jeśli wartości wyliczenia są sekwencyjne) lub prostaswitch
instrukcja z łatwością pokonałyby tę metodę . Jeśli masz w swoim tylko kilka wpisówEnum
, nie ma większego sensu dodawanie narzutu HashMap tylko po to, aby nie musieć aktualizowaćswitch
instrukcji. Ta metoda może wydawać się bardziej elegancka, ale jest też marnotrawstwem.Istnieje metoda statyczna,
values()
która jest udokumentowana, ale nie tam, gdzie można się jej spodziewać: 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];} }
W zasadzie możesz użyć just
values()[i]
, ale istnieją pogłoski, żevalues()
utworzy kopię tablicy za każdym razem, gdy zostanie ona wywołana.źródło
Będziesz musiał utworzyć nową statyczną metodę, w której iterujesz PcapLinkType.values () i porównujesz:
public static PcapLinkType forCode(int code) { for (PcapLinkType typе : PcapLinkType.values()) { if (type.getValue() == code) { return type; } } return null; }
Byłoby dobrze, gdyby było wywoływane rzadko. Jeśli jest wywoływany często, spójrz na
Map
optymalizację sugerowaną przez innych.źródło
Możesz zrobić coś takiego, aby automatycznie zarejestrować je wszystkie w kolekcji, za pomocą której można łatwo przekonwertować liczby całkowite na odpowiednie wyliczenie. (Przy okazji, dodawanie ich do mapy w konstruktorze wyliczenia jest niedozwolone . Fajnie jest uczyć się nowych rzeczy nawet po wielu latach używania Javy. :)
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); } }
źródło
jeśli masz takie enum
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; } }
wtedy możesz go używać jak
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
źródło
Jak mówi @MeBigFatGuy, z wyjątkiem tego, że możesz sprawić, by
static {...}
blok używał pętli nadvalues()
kolekcją:static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.getValue(), type); } }
źródło
Wiem, że to pytanie ma już kilka lat, ale ponieważ Java 8 w międzyczasie nas przyniosła
Optional
, pomyślałem, że zaproponuję rozwiązanie, które go wykorzysta (Stream
iCollectors
):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
jest jaknull
: reprezentuje przypadek, gdy nie ma (prawidłowej) wartości. Ale jest to bardziej bezpieczna dla typu alternatywanull
lub wartość domyślna, na przykładDLT_UNKNOWN
ponieważ można zapomnieć o sprawdzeniu przypadkównull
lubDLT_UNKNOWN
. Obie są poprawnymiPcapLinkType
wartościami! Natomiast nie można przypisaćOptional<PcapLinkType>
wartości do zmiennej typuPcapLinkType
.Optional
powoduje, że najpierw sprawdzasz prawidłową wartość.Oczywiście, jeśli chcesz zachować
DLT_UNKNOWN
zgodność ze starszymi wersjami lub z jakiegokolwiek innego powodu, nadal możesz użyćOptional
nawet w tym przypadku, używając,orElse()
aby określić to jako wartość domyślną: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); } }
źródło
Możesz dodać statyczną metodę w swoim wyliczeniu, która akceptuje an
int
jako parametr i zwracaPcapLinkType
.public static PcapLinkType of(int linkType) { switch (linkType) { case -1: return DLT_UNKNOWN case 0: return DLT_NULL; //ETC.... default: return null; } }
źródło
switch
instrukcji, jeśli dodasz nowe wyliczenie. Nie idealne, IMHO.Oto czego używam:
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); } }
źródło
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; } }
źródło
.values()
metodę?).--int
, ale to oczywiście literówka.null
zamiastDLT_UKNOWN
:)static final values[] = PcapLinkType.values()
?Nie ma możliwości eleganckiej obsługi typów wyliczeniowych opartych na liczbach całkowitych. Możesz pomyśleć o użyciu wyliczenia opartego na ciągach zamiast rozwiązania. Nie zawsze jest to preferowany sposób, ale nadal istnieje.
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); } }
źródło