Convert from enum ordinal to enum type
我有一个枚举类型
如何将序数转换为
使用Java 6 SE。
要将序数转换为其枚举重新表示,您可能需要执行以下操作:
1 | ReportTypeEnum value = ReportTypeEnum.values()[ordinal]; |
请注意数组边界。
请注意,对
关于如何缓存
编辑此答案以包括评论中给出的反馈
这几乎肯定是个坏主意。当然,如果序数事实上是持久的(例如,因为有人在URL上加了书签),这意味着您以后必须始终保留
为什么不使用
如果我要经常使用
1 2 3 4 | enum Suit { Hearts, Diamonds, Spades, Clubs; public static final Suit values[] = values(); } |
同时where.java:
1 | Suit suit = Suit.values[ordinal]; |
注意阵列边界。
我同意大多数人的看法,使用序数可能是一个坏主意。我通常通过给枚举一个私有的构造函数来解决这个问题,该构造函数可以例如一个db值,然后创建一个与jan答案中的函数类似的静态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | public ReportTypeEnum { R1(1), R2(2), R3(3), R4(4), R5(5), R6(6), R7(7), R8(8); private static Logger log = LoggerFactory.getLogger(ReportEnumType.class); private static Map<Integer, ReportTypeEnum> lookup; private Integer dbValue; private ReportTypeEnum(Integer dbValue) { this.dbValue = dbValue; } static { try { ReportTypeEnum[] vals = ReportTypeEnum.values(); lookup = new HashMap<Integer, ReportTypeEnum>(vals.length); for (ReportTypeEnum rpt: vals) lookup.put(rpt.getDbValue(), rpt); } catch (Exception e) { // Careful, if any exception is thrown out of a static block, the class // won't be initialized log.error("Unexpected exception initializing" + ReportTypeEnum.class, e); } } public static ReportTypeEnum fromDbValue(Integer dbValue) { return lookup.get(dbValue); } public Integer getDbValue() { return this.dbValue; } } |
现在,您可以在不更改查找的情况下更改顺序,反之亦然。
您可以使用静态查阅表格:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public enum Suit { spades, hearts, diamonds, clubs; private static final Map<Integer, Suit> lookup = new HashMap<Integer, Suit>(); static{ int ordinal = 0; for (Suit suit : EnumSet.allOf(Suit.class)) { lookup.put(ordinal, suit); ordinal+= 1; } } public Suit fromOrdinal(int ordinal) { return lookup.get(ordinal); } } |
这是我用的。我并没有假装它远不如上述简单的解决方案"高效"。它所做的是提供比"arrayindexoutofbounds"更清晰的异常消息,因为在上面的解决方案中使用了无效的序号。
它利用了这样一个事实:Enumset JavaDoc以自然顺序指定迭代器返回元素。如果这不正确,就有断言。
JUnit4测试演示了如何使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /** * convert ordinal to Enum * @param clzz may not be null * @param ordinal * @return e with e.ordinal( ) == ordinal * @throws IllegalArgumentException if ordinal out of range */ public static <E extends Enum<E> > E lookupEnum(Class<E> clzz, int ordinal) { EnumSet<E> set = EnumSet.allOf(clzz); if (ordinal < set.size()) { Iterator<E> iter = set.iterator(); for (int i = 0; i < ordinal; i++) { iter.next(); } E rval = iter.next(); assert(rval.ordinal() == ordinal); return rval; } throw new IllegalArgumentException("Invalid value" + ordinal +" for" + clzz.getName( ) +", must be <" + set.size()); } @Test public void lookupTest( ) { java.util.concurrent.TimeUnit tu = lookupEnum(TimeUnit.class, 3); System.out.println(tu); } |
这就是我用Proguard在Android上所做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public enum SomeStatus { UNINITIALIZED, STATUS_1, RESERVED_1, STATUS_2, RESERVED_2, STATUS_3;//do not change order private static SomeStatus[] values = null; public static SomeStatus fromInteger(int i) { if(SomeStatus.values == null) { SomeStatus.values = SomeStatus.values(); } if (i < 0) return SomeStatus.values[0]; if (i >= SomeStatus.values.length) return SomeStatus.values[0]; return SomeStatus.values[i]; } } |
它很短,我不需要担心Proguard中出现异常
您可以定义一个简单的方法,例如:
1 2 3 4 5 6 7 | public enum Alphabet{ A,B,C,D; public static Alphabet get(int index){ return Alphabet.values()[index]; } } |
使用方法如下:
1 |
所以有一种方法是do
1 2 3 4 5 6 7 | private enum ExampleEnum{ type0, type1, type2, type3; private static final ExampleEnum[] values = values(); public static ExampleEnum value(int ord) { return values[ord]; } } |
您可以使用
1 2 3 4 5 6 7 8 | public enum Suit implements java.io.Serializable, Comparable<Suit>{ spades, hearts, diamonds, clubs; private static final Suit [] lookup = Suit.values(); public Suit fromOrdinal(int ordinal) { if(ordinal< 1 || ordinal> 3) return null; return lookup[value-1]; } } |
测试类
1 2 3 4 5 6 7 8 9 |
我很感谢您与我们分享,如果您有一个更有效的代码,我的枚举是巨大的,经常被调用数千次。
每个枚举都有name(),它给出一个具有枚举成员名称的字符串。
鉴于
每个枚举都有一个
为什么有人会使用序数,我无法理解。它可能快纳秒,但如果枚举成员发生变化,这是不安全的,因为另一个开发人员可能不知道某些代码依赖于序数值(特别是在问题中引用的JSP页面中,网络和数据库开销完全支配了时间,而不是在字符串上使用整数)。