我有枚举类型ReportTypeEnum,在我所有的类的方法之间传递,但我需要在URL上传递这个,所以我使用序数方法来获得int值。在我的另一个JSP页面中获得它之后,我需要将它转换回ReportTypeEnum,以便我可以继续传递它。
如何将序数转换为ReportTypeEnum?
使用Java 6 SE。
我有枚举类型ReportTypeEnum,在我所有的类的方法之间传递,但我需要在URL上传递这个,所以我使用序数方法来获得int值。在我的另一个JSP页面中获得它之后,我需要将它转换回ReportTypeEnum,以便我可以继续传递它。
如何将序数转换为ReportTypeEnum?
使用Java 6 SE。
当前回答
如果我要大量使用values():
enum Suit {
Hearts, Diamonds, Spades, Clubs;
public static final Suit values[] = values();
}
同时wherever.java:
Suit suit = Suit.values[ordinal];
如果你想要数组是私有的,请自便:
private static final Suit values[] = values();
public static Suit get(int ordinal) { return values[ordinal]; }
...
Suit suit = Suit.get(ordinal);
注意数组的边界。
其他回答
要将一个序数转换为它的枚举表示,你可能想这样做:
ReportTypeEnum value = ReportTypeEnum.values()[ordinal];
请注意数组的边界。
注意,每次调用values()都会返回一个新克隆的数组,这可能会对性能产生负面影响。如果经常调用数组,可能需要缓存数组。
关于如何缓存值的代码示例()。
这个回答经过编辑,包含了评论中的反馈
这就是我用的。我并不是说它远不如上面那些简单的解决方案“有效”。当在上面的解决方案中使用无效序数值时,它所做的是提供比"ArrayIndexOutOfBounds"更清晰的异常消息。
它利用了EnumSet javadoc指定迭代器以自然顺序返回元素的事实。如果不正确,就有一个断言。
JUnit4测试演示了如何使用它。
/**
* 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);
}
这是我在Android上使用Proguard所做的:
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有一个异常
这几乎肯定是个坏主意。当然,如果序号实际上是持久化的(例如,因为有人已将URL标记为书签)——这意味着将来必须始终保留枚举顺序,这对代码维护者来说可能不太明显。
为什么不使用myEnumValue.name()(和解码通过reporttypeenume . valueof (s))来编码枚举?
有一种简单和坏的方法,也有一种相当简单和正确的方法。
首先,简单的和坏的(这些通常很受欢迎)。枚举类方法通过values()方法返回所有可用实例的数组,您可以通过数组索引访问枚举对象。
RenderingMode mode = RenderingMode.values()[index];
//Enum Class somewhere else
public enum RenderingMode
{
PLAYING,
PREVIEW,
VIEW_SOLUTION;
}
//RenderingMode.values()[0] will return RenderingMode.PLAYING
//RenderingMode.values()[1] will return RenderingMode.PREVIEW
//Why this is bad? Because it is linked to order of declaration.
//If you later changed the order here, it will impact all your existing logic around this.
public enum RenderingMode
{
PREVIEW,
VIEW_SOLUTION,
PLAYING;
}
//Now
//RenderingMode.values()[0] will return RenderingMode.PREVIEW
//RenderingMode.values()[1] will return RenderingMode.VIEW_SOLUTION
这是正确的做法。 在枚举类中创建一个静态方法fromInt。
public enum RenderingMode
{
PLAYING,
PREVIEW,
VIEW_SOLUTION;
public static RenderingModefromInt(int index)
{
//this is independent of order of declaration
switch (index)
{
case 0: return PLAYING;
case 1: return PREVIEW;
case 2: return VIEW_SOLUTION;
}
//Consider throwing Exception here
return null;
}
}