У меня такое перечисление:
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;
}
}
Теперь я получаю int от внешнего ввода и хочу соответствующий ввод - выброс исключения, если значение не существует, это нормально, но желательно, чтобы оно было DLT_UNKNOWN
в этом случае.
int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */
EnumMap
в качестве ключей используются перечисления. В этом случае OP хочет, чтобы перечисления были значениями.values()
(если ваши значения перечисления последовательны) или простойswitch
оператор легко превзойдет этот метод . Если у вас есть только несколько записей в вашем,Enum
тогда не имеет большого смысла добавлять накладные расходы на HashMap просто для удобства, чтобы не обновлятьswitch
оператор. Этот метод может показаться более элегантным, но он также расточителен.Там есть статический метод ,
values()
который является документально, но не там , где вы ожидаете: 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];} }
В принципе, вы можете использовать только
values()[i]
, но ходят слухи, чтоvalues()
каждый раз будет создавать копию массива при его вызове.источник
Вам нужно будет создать новый статический метод, в котором вы повторяете PcapLinkType.values () и сравниваете:
public static PcapLinkType forCode(int code) { for (PcapLinkType typе : PcapLinkType.values()) { if (type.getValue() == code) { return type; } } return null; }
Было бы хорошо, если бы он назывался редко. Если он вызывается часто, посмотрите на
Map
оптимизацию, предложенную другими.источник
Вы можете сделать что-то подобное, чтобы автоматически зарегистрировать их все в коллекции, с помощью которой затем легко преобразовать целые числа в соответствующее перечисление. (Кстати, добавление их на карту в конструкторе enum запрещено . Приятно узнавать что-то новое даже после многих лет использования 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); } }
источник
если у вас есть такое перечисление
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; } }
тогда вы можете использовать это как
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
источник
Как говорит @MeBigFatGuy, за исключением того, что вы можете заставить свой
static {...}
блок использовать цикл надvalues()
коллекцией:static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.getValue(), type); } }
источник
Я знаю, что этому вопросу несколько лет, но, поскольку Java 8 тем временем принесла нам
Optional
, я подумал, что предлагаю решение, использующее его (иStream
и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<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
похожеnull
: он представляет собой случай, когда нет (действительного) значения. Но это более безопасная для типов альтернативаnull
или значение по умолчанию, например,DLT_UNKNOWN
потому что вы можете забыть проверить регистрыnull
илиDLT_UNKNOWN
. ОбаPcapLinkType
значения допустимы ! Напротив, вы не можете присвоитьOptional<PcapLinkType>
значение переменной типаPcapLinkType
.Optional
заставляет вас сначала проверять допустимое значение.Конечно, если вы хотите сохранить
DLT_UNKNOWN
для обратной совместимости или по любой другой причине, вы все равно можете использоватьOptional
даже в этом случае, используяorElse()
для указания его в качестве значения по умолчанию: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); } }
источник
Вы можете добавить статический метод в свое перечисление, которое принимает
int
в качестве параметра и возвращаетPcapLinkType
.public static PcapLinkType of(int linkType) { switch (linkType) { case -1: return DLT_UNKNOWN case 0: return DLT_NULL; //ETC.... default: return null; } }
источник
switch
оператор, если вы добавите новое перечисление. Не идеальный, ИМХО.Вот что я использую:
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; } }
источник
.values()
метод?).--int
, но это явно опечатка.null
вместоDLT_UKNOWN
:)static final values[] = PcapLinkType.values()
?Невозможно элегантно обрабатывать перечисляемые типы на основе целых чисел. Вы можете подумать об использовании строкового перечисления вместо вашего решения. Не всегда предпочтительный способ, но он все еще существует.
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); } }
источник