将整数值转换为匹配的Java Enum

我有这样的枚举:

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; } } 

现在我从外部input获取一个int,并希望匹配的input – 如果一个值不存在,抛出一个exception是好的,但最好是在这种情况下,我想它是DLT_UNKNOWN

 int val = in.readInt(); PcapLinkType type = ???; /*convert val to a PcapLinkType */ 

您需要手动执行此操作,方法是在将整数映射到枚举的类中添加一个静态映射,例如

 private static final Map<Integer, PcapLinkType> intToTypeMap = new HashMap<Integer, PcapLinkType>(); 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; } 

有一个静态方法values() logging,但不是你所期望的: 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];} } 

原则上,只能使用values()[i] ,但有传言说values()会在每次调用时创build一个数组的副本。

你将不得不做一个新的静态方法,你迭代PcapLinkType.values()并比较:

 public static PcapLinkType forCode(int code) { for (PcapLinkType typе : PcapLinkType.values()) { if (type.getValue() == code) { return type } } return null; } 

这很好,如果它被称为很less。 如果频繁调用,则查看其他人build议的Map优化。

如果你有这样的枚举

 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 */ 

你可以做这样的事情,自动注册到一个集合,然后轻松地将整数转换为相应的枚举。 (顺便说一句,在枚举构造函数中将它们添加到地图中是不允许的,即使经过多年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); } } 

正如@MeBigFatGuy所说,除了你可以使你的static {...}块在values()集合上使用一个循环:

 static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.getValue(), type); } } 

我知道这个问题已经有几年了,但是正如Java 8在此期间带给我们的是Optional ,我想我会提供一个使用它的解决scheme(以及StreamCollectors ):

 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 :它代表没有(有效)值的情况。 但是这是一个更types安全的替代方法,可以是null或默认值,例如DLT_UNKNOWN因为您可能忘记检查nullDLT_UNKNOWN情况。 它们都是有效的PcapLinkType值! 相反,您不能将Optional<PcapLinkType>值分配给types为PcapLinkType的variables。 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); } } 

这是我使用的:

 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); } } 

您可以在您的枚举中添加一个静态方法,该方法接受一个int作为参数并返回一个PcapLinkType

 public static PcapLinkType of(int linkType) { switch (linkType) { case -1: return DLT_UNKNOWN case 0: return DLT_NULL; //ETC.... default: return null; } } 
 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; } }