我有枚举类型ReportTypeEnum,在我所有的类的方法之间传递,但我需要在URL上传递这个,所以我使用序数方法来获得int值。在我的另一个JSP页面中获得它之后,我需要将它转换回ReportTypeEnum,以便我可以继续传递它。

如何将序数转换为ReportTypeEnum?

使用Java 6 SE。


当前回答

这几乎肯定是个坏主意。当然,如果序号实际上是持久化的(例如,因为有人已将URL标记为书签)——这意味着将来必须始终保留枚举顺序,这对代码维护者来说可能不太明显。

为什么不使用myEnumValue.name()(和解码通过reporttypeenume . valueof (s))来编码枚举?

其他回答

如果我要大量使用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()都会返回一个新克隆的数组,这可能会对性能产生负面影响。如果经常调用数组,可能需要缓存数组。

关于如何缓存值的代码示例()。


这个回答经过编辑,包含了评论中的反馈

你可以使用静态查找表:

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测试演示了如何使用它。

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

安全第一(使用Kotlin):

// Default to null
EnumName.values().getOrNull(ordinal)

// Default to a value
EnumName.values().getOrElse(ordinal) { EnumName.MyValue }