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

如何将序数转换为ReportTypeEnum?

使用Java 6 SE。


当前回答

So one way is to doExampleEnum valueOfOrdinal = ExampleEnum.values()[ordinal]; which works and its easy, however, as mentioned before, ExampleEnum.values() returns a new cloned array for every call. That can be unnecessarily expensive. We can solve that by caching the array like so ExampleEnum[] values = values(). It is also "dangerous" to allow our cached array to be modified. Someone could write ExampleEnum.values[0] = ExampleEnum.type2; So I would make it private with an accessor method that does not do extra copying.

private enum ExampleEnum{
    type0, type1, type2, type3;
    private static final ExampleEnum[] values = values();
    public static ExampleEnum value(int ord) {
        return values[ord];
    }
}

您可以使用exampleenumeration .value(ordinal)来获取与ordinal关联的枚举值

其他回答

这几乎肯定是个坏主意。当然,如果序号实际上是持久化的(例如,因为有人已将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;
    }
}

安全第一(使用Kotlin):

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

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

这就是我用的。我并不是说它远不如上面那些简单的解决方案“有效”。当在上面的解决方案中使用无效序数值时,它所做的是提供比"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);
}

通过这种方式,您可以不依赖于编译时泛型解析(因此您可以随时创建枚举类实例,即使是使用class . formame创建的类型)

public Object getInstance(Class enumClazz, int ordinal) throws Exception {
    Object[] allEnums = enumClazz.getDeclaredMethod("values", Object[].class).invoke(null, null);
    return allEnums[ordinal];
}