Cuando trabajo con variables / parámetros que solo pueden tomar un número finito de valores, trato de usar siempre Java enum
, como en
public enum BonusType {
MONTHLY, YEARLY, ONE_OFF
}
Mientras permanezca dentro de mi código, eso funciona bien. Sin embargo, a menudo necesito interactuar con otro código que usa valores simples int
(o String
) para el mismo propósito, o necesito leer / escribir desde / hacia una base de datos donde los datos se almacenan como un número o cadena.
En ese caso, me gustaría tener una forma conveniente de asociar cada valor de enumeración con un número entero, de modo que pueda convertir en ambos sentidos (en otras palabras, necesito una "enumeración reversible").
Pasar de enum a int es fácil:
public enum BonusType {
public final int id;
BonusType(int id) {
this.id = id;
}
MONTHLY(1), YEARLY(2), ONE_OFF(3);
}
Entonces puedo acceder al valor int como BonusType x = MONTHLY; int id = x.id;
.
Sin embargo, no veo una buena manera de lo contrario, es decir, pasar de int a enum. Idealmente, algo como
BonusType bt = BonusType.getById(2);
Las únicas soluciones que se me ocurren son:
- Ponga un método de búsqueda en la enumeración, que se usa
BonusType.values()
para llenar un mapa "int -> enum", luego lo almacena en caché y lo usa para búsquedas. Funcionaría, pero tendría que copiar este método de forma idéntica en cada enumeración que uso :-(. - Coloque el método de búsqueda en una clase de utilidad estática. Entonces solo necesitaría un método de "búsqueda", pero tendría que jugar con la reflexión para que funcione para una enumeración arbitraria.
Ambos métodos parecen terriblemente incómodos para un problema tan simple (?).
¿Alguna otra idea / conocimiento?
fuente
ordinal()
.ordinal()
), o son decididos por fuerzas externas?Respuestas:
http://www.javaspecialists.co.za/archive/Issue113.html
La solución comienza similar a la suya con un valor int como parte de la definición de enumeración. Luego pasa a crear una utilidad de búsqueda basada en genéricos:
Esta solución es agradable y no requiere 'jugar con la reflexión' porque se basa en el hecho de que todos los tipos de enumeración heredan implícitamente la interfaz Enum.
fuente
Number
lugar deByte
, porque mi valor de respaldo podría ser mayor en tamaño.enum → int
int → enum
Cadena → enumeración
enum → Cadena
Una nota al margen:
como señala correctamente,
ordinal()
puede ser "inestable" de una versión a otra. Esta es la razón exacta por la que siempre almaceno constantes como cadenas en mis bases de datos. (¡En realidad, cuando uso MySql, los guardo como enumeraciones de MySql !)fuente
BonusType.valueOf("MONTHLY")
)ordinal()
me parece una solución problemática, porque se romperá cuando se reorganice la lista de valores de enumeración o se elimine un valor. Además, esto solo es práctico si los valores int son 0 ... n (que a menudo he descubierto que no es el caso).values()
matriz solo funcionará si todos sus valores están indexados en 0 para su identificación y se declaran en orden. (He probado esto para verificar que si se declaraFOO(0), BAR(2), BAZ(1);
quevalues[1] == BAR
, yvalues[2] == BAZ
pese a los identificadores se ha pasado.)double
).Encontré esto en la web, fue muy útil y simple de implementar. Esta solución NO fue hecha por mí.
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
}
fuente
Parece que las respuestas a esta pregunta están desactualizadas con el lanzamiento de Java 8.
fuente
Collectors.toMap()
estarFunctions.identity()
en lugar denull
?org.apache.commons.lang.enums.ValuedEnum;
Para ahorrarme escribir un montón de código repetitivo o duplicar código para cada Enum, utilicé Apache Commons Lang's
ValuedEnum
lugar.Definición :
Uso:
int -> ValuedEnum:
fuente
Quizás podrías usar algo como
Eso reduciría la necesidad de reflexionar en su clase de servicios públicos.
fuente
En este código, para una búsqueda permanente e intensa, tengo memoria o proceso para usar, y selecciono memoria, con array convertidor como índice. Espero que sea de ayuda
fuente
Usa una interfaz para mostrarle quién manda.
Y el resultado:
fuente
Tanto el
.ordinal()
comovalues()[i]
son inestables ya que dependen del orden de enumeraciones. Por lo tanto, si cambia el orden de las enumeraciones o agrega / elimina algunas, su programa se romperá.Aquí hay un método simple pero efectivo para mapear entre enum e int.
Aplicarlo para cuerdas no debería ser difícil.
fuente
Paso 1 Definir un
interface
EnumConverterPaso 2
Crear un nombre de clase ReverseEnumMap
Paso 3
Vaya a su
Enum
clase yimplement
, porEnumConverter<ContentType>
supuesto, anule los métodos de interfaz. También necesita inicializar un ReverseEnumMap estático.Paso 4
Ahora cree un
Communication
archivo de clase y llamar a su nuevo método para convertir unaEnum
aString
yString
aEnum
. Acabo de poner el método principal con fines explicativos.Haga clic para obtener una explicación completa
fuente
ContentType convert(String pKey)
estática, lo que elimina la necesidad de laCommunication
clase y fue más de mi agrado. +1No estoy seguro de si es lo mismo en Java, pero los tipos de enumeración en C también se asignan automáticamente a números enteros, por lo que puede usar el tipo o el entero para acceder a él. ¿Ha intentado simplemente acceder a él con un número entero?
fuente
.ordinal()
método puede acceder a él . (De otra manera, useBonusType.values()[i]
). Pero en el ejemplo citado anteriormente, los índices aquí y los valores externos no coinciden.Realmente una gran pregunta :-) Usé una solución similar a la del señor Ferguson hace algún tiempo. Nuestra enumeración descompilada se ve así:
Al ver esto, es evidente por qué
ordinal()
es inestable. Es eli
insuper(s, i);
. También soy pesimista de que pueda pensar en una solución más elegante que las que ya enumeró. Después de que todas las enumeraciones son clases como cualquier clase final.fuente
En aras de la integridad, aquí hay un enfoque genérico para recuperar valores de enumeración por índice de cualquier tipo de enumeración. Mi intención era hacer que el método se viera y se sintiera como Enum.valueOf (Class, String) . Fyi, copié este método de aquí .
Los problemas relacionados con el índice (ya discutidos en profundidad aquí) todavía se aplican.
fuente
MyEnumType.values()
, sin necesidad de un método auxiliar estático.fuente
Necesitaba algo diferente porque quería usar un enfoque genérico. Estoy leyendo la enumeración hacia y desde matrices de bytes. Aquí es donde se me ocurre:
Ejemplo de enumeraciones:
}
fuente
Solo porque la respuesta aceptada no es autónoma:
Código de soporte:
Ejemplo de uso:
fuente
dado:
enumeración pública BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}
BonusType bonus = YEARLY;
System.out.println (bonus.Ordinal () + ":" + bonus)
Salida: 1: ANUAL
fuente
Si tienes un auto de clase
Y la propiedad Color es una clase
Y quieres convertir Color a Enum
Simplemente agregue un método en la clase Color para convertir Color en ColorEnum
y dentro de ColorEnum implementa el método getById ()
Ahora puedes usar un classMap
fuente