从枚举序号转换为枚举类型

本文讨论如何在Java中将枚举的序数转换回枚举类型。在URL传递中使用枚举的ordinal()方法得到int值,然后在JSP页面中需要将其转换回枚举。建议使用枚举的name()方法配合valueOf()方法进行转换,以确保安全性。此外,还提供了使用EnumSet和静态工厂方法的替代解决方案。
摘要由CSDN通过智能技术生成

本文翻译自:Convert from enum ordinal to enum type

I've the enum type ReportTypeEnum that get passed between methods in all my classes but I then need to pass this on the URL so I use the ordinal method to get the int value. 我在我的所有类中的方法之间传递了枚举类型ReportTypeEnum ,但是我需要在URL上传递它,所以我使用序数方法来获取int值。 After I get it in my other JSP page, I need to convert it to back to an ReportTypeEnum so that I can continue passing it. 在我的其他JSP页面中获取它之后,我需要将其转换回ReportTypeEnum以便我可以继续传递它。

How can I convert ordinal to the ReportTypeEnum ? 如何将序数转换为ReportTypeEnum

Using Java 6 SE. 使用Java 6 SE。


#1楼

参考:https://stackoom.com/question/2yEs/从枚举序号转换为枚举类型


#2楼

Every enum has name(), which gives a string with the name of enum member. 每个枚举都有name(),它给出一个名为enum成员的字符串。

Given enum Suit{Heart, Spade, Club, Diamond} , Suit.Heart.name() will give Heart . 鉴于enum Suit{Heart, Spade, Club, Diamond}Suit.Heart.name()将给予Heart

Every enum has a valueOf() method, which takes an enum type and a string, to perform the reverse operation: 每个枚举都有一个valueOf()方法,它采用枚举类型和字符串来执行反向操作:

Enum.valueOf(Suit.class, "Heart") returns Suit.Heart . Enum.valueOf(Suit.class, "Heart")返回Suit.Heart

Why anyone would use ordinals is beyond me. 为什么有人会使用序数超出我的范围。 It may be nanoseconds faster, but it is not safe, if the enum members change, as another developer may not be aware some code is relying on ordinal values (especially in the JSP page cited in the question, network and database overhead completely dominates the time, not using an integer over a string). 它可能要快几纳秒,但是如果枚举成员发生变化则不安全,因为另一个开发人员可能不知道某些代码依赖于序数值(特别是在问题中引用的JSP页面中,网络和数据库开销完全占主导地位)时间,不使用字符串上的整数)。


#3楼

If I'm going to be using values() a lot: 如果我要使用values()很多:

enum Suit {
   Hearts, Diamonds, Spades, Clubs;
   public static final Suit values[] = values();
}

Meanwhile wherever.java: 同时wherever.java:

Suit suit = Suit.values[ordinal];

Mind your array bounds. 注意阵列界限。


#4楼

I agree with most people that using ordinal is probably a bad idea. 我同意大多数人使用序数可能是一个坏主意。 I usually solve this problem by giving the enum a private constructor that can take for example a DB value then create a static fromDbValue function similar to the one in Jan's answer. 我通常通过给枚举一个私有构造函数来解决这个问题,该构造函数可以采用例如DB值,然后创建一个类似于Jan答案中的静态fromDbValue函数。

public enum 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;
    }

}

Now you can change the order without changing the lookup and vice versa. 现在您可以在不更改查找的情况下更改顺序,反之亦然。


#5楼

This is what I use. 这就是我使用的。 I make no pretense that it's far less "efficient" than the simpler solutions above. 我并没有假装它比上面简单的解决方案更“有效”。 What it does do is provide a much clearer exception message than "ArrayIndexOutOfBounds" when an invalid ordinal value is used in the solution above. 当在上面的解决方案中使用无效的序数值时,它所做的是提供比“ArrayIndexOutOfBounds”更清晰的异常消息。

It utilizes the fact that EnumSet javadoc specifies the iterator returns elements in their natural order. 它利用了EnumSet javadoc指定迭代器以其自然顺序返回元素的事实。 There's an assert if that's not correct. 如果这不正确,就会有一个断言。

The JUnit4 Test demonstrates how it's used. 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);
}

#6楼

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];
  }
}

the test class 考试班

public class MainTest {
    public static void main(String[] args) {
        Suit d3 = Suit.diamonds;
        Suit d3Test = Suit.fromOrdinal(2);
        if(d3.equals(d3Test)){
            System.out.println("Susses");
        }else System.out.println("Fails");
    }
}

I appreciate that you share with us if you have a more efficient code, My enum is huge and constantly called thousands of times. 如果你有更高效的代码,我很感激你与我们分享,我的枚举是巨大的,不断被召唤数千次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值