从枚举序号转换为枚举types
我有枚举typesReportTypeEnum
获取所有类中的方法之间传递,但我需要通过这个URL,所以我使用序数方法来获取int值。 我得到它在我的其他JSP页面后,我需要将其转换回ReportTypeEnum
以便我可以继续传递它。
如何将序号转换为ReportTypeEnum
?
使用Java 6 SE。
要将一个序号转换为它的enum represantation,你可能需要这样做:
ReportTypeEnum value = ReportTypeEnum.values()[ordinal];
请注意数组边界。
请注意,每次调用values()
返回一个新克隆的数组,这可能会对性能造成负面影响。 如果要经常调用数组,可能需要caching该数组。
代码示例如何cachingvalues()
。
这个答案被编辑,包括在评论中给出的反馈
这几乎肯定是一个坏主意 。 当然,如果序号事实上持续存在(例如,因为某人已经将URLjoin书签) – 这意味着您将来必须始终保留enum
sorting,这可能不会明显地将维护人员编码到队列中。
为什么不使用myEnumValue.name()
编码enum
(并通过ReportTypeEnum.valueOf(s)
解码)?
如果我打算使用values()
很多:
enum Suit { Hearts, Diamonds, Spades, Clubs; public static final Suit values[] = values(); }
同时wherever.java:
Suit suit = Suit.values[ordinal];
注意你的数组边界。
你可以使用静态查找表:
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); } }
我同意大多数人使用序数可能是一个坏主意。 我通常通过给枚举一个私有构造函数来解决这个问题,该构造函数可以采用一个DB值,然后创build一个类似于Jan的答案的静态fromDbValue
函数。
public 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; } }
现在,您可以更改顺序而不更改查找,反之亦然。
这是我用的。 我不假装它比上面简单的解决scheme要less得多。 在上面的解决scheme中使用无效序数值时,它所做的是提供比“ArrayIndexOutOfBounds”更清晰的exception消息。
它利用了EnumSet javadoc指定迭代器以自然顺序返回元素的事实。 有一个断言,如果这是不正确的。
JUnit4testing演示了如何使用它。
/** * 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); }
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]; } }
testing类
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"); } }
我很感谢你与我们分享,如果你有一个更有效的代码,我的枚举是巨大的,并不断被称为数千次。
假设你有以下的枚举:
public enum ErrorCodes { BUSINESS_ERROR(100), SERVER_ERROR(500), NETWORK_ERROR(1000); }
默认情况下,你不能通过它的数值检索一个ErrorCode实例,因为java没有提供任何方法来检索一个字段的Enum实例。
为了做到这一点,我通常在Enum类中公开一个静态HashMap,它将每个值映射到相应的Enum实例,如下所示:
public enum ErrorCodes { BUSINESS_ERROR(100), SERVER_ERROR(500), NETWORK_ERROR(1000); private int errorCode; private static Map<Integer, ErrorCodes> errorCodeByErrorNumber = new HashMap<Integer, ErrorCodes>(); static { for (ErrorCodes errorCode : ErrorCodes.values()) { errorCodeByErrorNumber.put(errorCode.getErrorCode(), errorCode); } } private ErrorCodes(int errorCode) { this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } public static ErrorCodes getErrorCodeByNumber(Integer errorNumber) { return errorCodeByErrorNumber.get(errorNumber); } }
对于更常见的Enum操作,请检查: 如何在java中使用Enums
每个枚举都有name(),它给出了一个名为enum成员的string。
鉴于enum Suit{Heart, Spade, Club, Diamond}
, Suit.Heart.name()
将给予Heart
。
每个枚举都有一个valueOf()
方法,它使用一个枚举types和一个string来执行反向操作:
Enum.valueOf(Suit.class, "Heart")
返回Suit.Heart
。
为什么有人会使用序数是超出我的。 如果枚举成员发生变化,可能会更快,但不安全,因为另一个开发人员可能不知道某些代码依赖于序数值(特别是在问题中引用的JSP页面中,networking和数据库开销完全支配时间,而不是使用整数string)。