我有枚举类型ReportTypeEnum,在我所有的类的方法之间传递,但我需要在URL上传递这个,所以我使用序数方法来获得int值。在我的另一个JSP页面中获得它之后,我需要将它转换回ReportTypeEnum,以便我可以继续传递它。
如何将序数转换为ReportTypeEnum?
使用Java 6 SE。
我有枚举类型ReportTypeEnum,在我所有的类的方法之间传递,但我需要在URL上传递这个,所以我使用序数方法来获得int值。在我的另一个JSP页面中获得它之后,我需要将它转换回ReportTypeEnum,以便我可以继续传递它。
如何将序数转换为ReportTypeEnum?
使用Java 6 SE。
当前回答
每个枚举都有name(),它给出一个包含枚举成员名称的字符串。
给定一个花色{红心,黑桃,梅花,方块},Suit.Heart.name()将给出红心。
每个枚举都有一个valueOf()方法,该方法接受一个枚举类型和一个字符串,以执行相反的操作:
枚举. valueof (Suit.class, "Heart")返回Suit.Heart。
我真搞不懂为什么会有人用序数。它可能会快几纳秒,但如果枚举成员发生变化,则不安全,因为另一个开发人员可能不知道某些代码依赖于序数值(特别是在问题中引用的JSP页面中,网络和数据库开销完全占据了时间,而不是使用整数而不是字符串)。
其他回答
这是我在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有一个异常
安全第一(使用Kotlin):
// Default to null
EnumName.values().getOrNull(ordinal)
// Default to a value
EnumName.values().getOrElse(ordinal) { EnumName.MyValue }
有一种简单和坏的方法,也有一种相当简单和正确的方法。
首先,简单的和坏的(这些通常很受欢迎)。枚举类方法通过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;
}
}
这几乎肯定是个坏主意。当然,如果序号实际上是持久化的(例如,因为有人已将URL标记为书签)——这意味着将来必须始终保留枚举顺序,这对代码维护者来说可能不太明显。
为什么不使用myEnumValue.name()(和解码通过reporttypeenume . valueof (s))来编码枚举?
这就是我用的。我并不是说它远不如上面那些简单的解决方案“有效”。当在上面的解决方案中使用无效序数值时,它所做的是提供比"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);
}