Convertir de enum ordinal a enum type

Tengo el tipo enum ReportTypeEnum que se pasa entre los métodos en todas mis clases, pero luego necesito pasar esto en la URL, así que utilizo el método ordinal para obtener el valor int. Después de obtenerlo en mi otra página JSP, necesito convertirlo a un ReportTypeEnum para que pueda seguir pasándolo.

¿Cómo puedo convertir ordinal a ReportTypeEnum ?

Usando Java 6 SE.

Para convertir un ordinal en su represación enum, puede hacer esto:

 ReportTypeEnum value = ReportTypeEnum.values()[ordinal]; 

Por favor, tenga en cuenta los límites de la matriz.

Tenga en cuenta que cada llamada a values() devuelve una matriz recién clonada que podría afectar el rendimiento de una manera negativa. Es posible que desee almacenar en caché la matriz si se va a llamar con frecuencia.

Ejemplo de código sobre cómo almacenar en caché los values() .


Esta respuesta fue editada para incluir los comentarios recibidos dentro de los comentarios

Esto es casi seguro una mala idea . Ciertamente, si el ordinal es de facto persistente (por ejemplo, porque alguien ha marcado el URL), significa que siempre debe conservar el orden enum en el futuro, lo que puede no ser obvio para los encargados del código más adelante.

¿Por qué no codificar la enum utilizando myEnumValue.name() (y decodificar a través de ReportTypeEnum.valueOf(s) ) en su lugar?

Si voy a usar values() mucho:

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

Mientras tanto, donde sea.java:

 Suit suit = Suit.values[ordinal]; 

Tenga en cuenta los límites de su matriz.

Puede usar una tabla de búsqueda estática:

 public enum Suit { spades, hearts, diamonds, clubs; private static final Map lookup = new HashMap(); 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); } } 

Estoy de acuerdo con la mayoría de las personas que usar ordinal es probablemente una mala idea. Por lo general, resuelvo este problema dando a la enumeración un constructor privado que puede tomar, por ejemplo, un valor de DB y luego crea una función estática fromDbValue similar a la de la respuesta de Jan.

 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 lookup; private Integer dbValue; private ReportTypeEnum(Integer dbValue) { this.dbValue = dbValue; } static { try { ReportTypeEnum[] vals = ReportTypeEnum.values(); lookup = new HashMap(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; } } 

Ahora puede cambiar el orden sin cambiar la búsqueda y viceversa.

Esto es lo que uso No pretendo que sea mucho menos “eficiente” que las soluciones más simples anteriores. Lo que hace es proporcionar un mensaje de excepción mucho más claro que “ArrayIndexOutOfBounds” cuando se utiliza un valor ordinal no válido en la solución anterior.

Utiliza el hecho de que EnumSet javadoc especifica que el iterador devuelve los elementos en su orden natural. Hay una afirmación si eso no es correcto.

La prueba JUnit4 demuestra cómo se usa.

  /** * 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 lookupEnum(Class clzz, int ordinal) { EnumSet set = EnumSet.allOf(clzz); if (ordinal < set.size()) { Iterator 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{ 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]; } } 

la clase de prueba

 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"); } } 

Aprecio que compartas con nosotros si tienes un código más eficiente. Mi enum es enorme y se llama constantemente miles de veces.

Supongamos que tiene la siguiente enumeración:

 public enum ErrorCodes { BUSINESS_ERROR(100), SERVER_ERROR(500), NETWORK_ERROR(1000); } 

De forma predeterminada, no podría recuperar una instancia de ErrorCode por su valor numérico, ya que Java no proporciona ninguna forma de recuperar la instancia de Enum por un campo.

Para hacer eso, normalmente expongo un hashmap estático dentro de la clase Enum que asigna cada valor a su instancia Enum correspondiente de la siguiente manera:

 public enum ErrorCodes { BUSINESS_ERROR(100), SERVER_ERROR(500), NETWORK_ERROR(1000); private int errorCode; private static Map errorCodeByErrorNumber = new HashMap(); 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); } } 

Para operaciones Enum más comunes, verifique esto: Cómo usar Enums en java

Esto es lo que hago en Android con 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]; } } 

es corto y no necesito preocuparme por tener una excepción en Proguard

Cada enumeración tiene nombre (), que da una cadena con el nombre del miembro enum.

Dado el enum Suit{Heart, Spade, Club, Diamond} , Suit.Heart.name() le dará Heart .

Cada enumeración tiene un método valueOf() , que toma un tipo de enumeración y una cadena, para realizar la operación inversa:

Enum.valueOf(Suit.class, "Heart") devuelve Suit.Heart .

Por qué alguien usaría los ordinales está más allá de mí. Puede ser nanosegundos más rápido, pero no es seguro si los miembros enum cambian, ya que otro desarrollador puede no estar consciente de que algún código se basa en valores ordinales (especialmente en la página JSP citada en la pregunta, la red y la sobrecarga de la base de datos dominan por completo tiempo, no usando un número entero sobre una cadena).