Hoy estaba navegando por algunas preguntas en este sitio y encontré una mención de un enum
ser utilizado en un patrón único sobre los supuestos beneficios de seguridad de los hilos para dicha solución.
Nunca he usado enum
sy he estado programando en Java durante más de un par de años. Y aparentemente cambiaron mucho. Ahora incluso hacen un apoyo total de OOP dentro de sí mismos.
Respuestas:
Siempre debe usar enumeraciones cuando una variable (especialmente un parámetro de método) solo puede extraer una de un pequeño conjunto de valores posibles. Los ejemplos serían cosas como constantes de tipo (estado del contrato: "permanente", "temp", "aprendiz") o banderas ("ejecutar ahora", "diferir la ejecución").
Si usa enumeraciones en lugar de números enteros (o códigos de cadena), aumenta la verificación en tiempo de compilación y evita que los errores pasen constantes no válidas, y documenta qué valores son legales para usar.
Por cierto, el uso excesivo de enumeraciones puede significar que sus métodos hacen demasiado (a menudo es mejor tener varios métodos separados, en lugar de un método que tome varios indicadores que modifiquen lo que hace), pero si tiene que usar indicadores o códigos de tipo, enumeraciones son el camino a seguir.
Como ejemplo, ¿cuál es mejor?
versus
Una llamada a un método como:
luego se convierte en:
En el segundo ejemplo, queda claro de inmediato qué tipos están permitidos, los documentos y la implementación no pueden estar fuera de sincronización, y el compilador puede aplicar esto. Además, una llamada no válida como
Ya no es posible.
fuente
you should *always* use enums when a variable can only take one out of a small set of possible values
. Usar valores constantes como 'indicador binario' (con lógicaor
) puede ser útil para aplicaciones en tiempo real en las que tiene poca memoria.¿Por qué usar cualquier función de lenguaje de programación? La razón por la que tenemos idiomas es para
Las enumeraciones mejoran tanto la probabilidad de corrección como la legibilidad sin escribir mucho repetitivo. Si está dispuesto a escribir repeticiones, puede "simular" enumeraciones:
Ahora puedes escribir:
La repetitiva anterior tiene el mismo efecto que
Ambos proporcionan el mismo nivel de comprobación de ayuda del compilador. Boilerplate es simplemente más tipeo. Pero ahorrar mucho tipeo hace que el programador sea más eficiente (ver 1), por lo que es una característica que vale la pena.
También vale la pena por al menos una razón más:
Cambiar declaraciones
Una cosa que la
static final
simulación de enumeración anterior no le brinda son buenosswitch
casos. Para los tipos de enumeración, el conmutador Java utiliza el tipo de su variable para inferir el alcance de los casos de enumeración, por lo que para loenum Color
anterior simplemente necesita decir:Tenga en cuenta que no está
Color.RED
en los casos. Si no usa enum, la única forma de usar cantidades con nombreswitch
es algo como:Pero ahora una variable para contener un color debe tener tipo
int
. El buen compilador comprobando la enumeración y elstatic final
simulación se ha ido. No feliz.Un compromiso es usar un miembro de valor escalar en la simulación:
Ahora:
Pero tenga en cuenta, ¡aún más repetitivo!
Usando una enumeración como un singleton
En la plantilla anterior puede ver por qué una enumeración proporciona una forma de implementar un singleton. En lugar de escribir:
y luego accediendo con
solo podemos decir
lo que nos da lo mismo. Podemos evitar esto porque las enumeraciones de Java se implementan como clases completas con solo un poco de azúcar sintáctica esparcida por la parte superior. Esto es de nuevo menos repetitivo, pero no es obvio a menos que el idioma te sea familiar. También me gusta el hecho de que se obtiene de las diversas funciones de enumeración a pesar de que no tienen mucho sentido para el singleton:
ord
yvalues
, etc (De hecho, hay una simulación más complicado cuandoColor extends Integer
que trabajará con el interruptor, pero es tan complicado que sea aún más muestra claramente por quéenum
es una mejor idea).Hilo de seguridad
La seguridad de los hilos es un problema potencial solo cuando los singletons se crean perezosamente sin bloqueo.
Si muchos hilos llaman
getInstance
simultáneamente mientrasINSTANCE
todavía es nulo, se puede crear cualquier número de instancias. Esto es malo. La única solución es agregarsynchronized
acceso para proteger la variableINSTANCE
.Sin embargo, el
static final
código anterior no tiene este problema. Crea la instancia con entusiasmo en el tiempo de carga de la clase. La carga de clases está sincronizada.El
enum
singleton es efectivamente perezoso porque no se inicializa hasta el primer uso. La inicialización de Java también está sincronizada, por lo que varios subprocesos no pueden inicializar más de una instancia deINSTANCE
. Estás obteniendo un singleton perezosamente inicializado con muy poco código. Lo único negativo es la sintaxis bastante oscura. Necesitas conocer el idioma o comprender a fondo cómo funciona la carga de clases y la inicialización para saber qué está sucediendo.fuente
static final
los campos se inicializan en el momento de inicialización de la clase , no en el tiempo de carga. Es exactamente lo mismo que con laenum
inicialización constante (de hecho, son idénticos bajo el capó). Es por eso que tratar de implementar un código de inicialización "inteligente" para perezosos siempre fue inútil, incluso en la primera versión de Java.Además de los casos de uso ya mencionados, a menudo encuentro enums útiles para implementar el patrón de estrategia, siguiendo algunas pautas básicas de OOP:
El ejemplo más simple sería un conjunto de
Comparator
implementaciones:Este "patrón" puede usarse en escenarios mucho más complejos, haciendo un uso extensivo de todos los beneficios que vienen con la enumeración: iterar sobre las instancias, confiar en su orden implícito, recuperar una instancia por su nombre, métodos estáticos que proporcionan la instancia correcta para contextos específicos, etc. Y aún tiene todo esto oculto detrás de la interfaz para que su código funcione con implementaciones personalizadas sin modificación en caso de que desee algo que no esté disponible entre las "opciones predeterminadas".
He visto que esto se aplicó con éxito para modelar el concepto de granularidad de tiempo (diario, semanal, etc.) donde toda la lógica se encapsulaba en una enumeración (elegir la granularidad correcta para un rango de tiempo dado, el comportamiento específico vinculado a cada granularidad como constante métodos, etc.). Y aún así,
Granularity
según lo visto por la capa de servicio era simplemente una interfaz.fuente
CASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }
. Una ventaja que aún no se menciona es que obtienes un sólido soporte de serialización; el formulario persistente solo contiene el nombre de la clase y el nombre constante, sin depender de los detalles de implementación de sus comparadores.Algo que ninguna de las otras respuestas ha cubierto que hace que las enumeraciones sean particularmente poderosas es la capacidad de tener métodos de plantilla . Los métodos pueden ser parte de la enumeración base y ser anulados por cada tipo. Y, con el comportamiento adjunto a la enumeración, a menudo elimina la necesidad de construcciones if-else o declaraciones de cambio como lo demuestra esta publicación de blog : ¿dónde
enum.method()
se ejecuta lo que originalmente se ejecutaría dentro del condicional? El mismo ejemplo también muestra el uso de importaciones estáticas con enumeraciones y produce un código similar a DSL mucho más limpio.Algunas otras cualidades interesantes incluyen el hecho de que las enumeraciones proporcionan la implementación de
equals()
,toString()
yhashCode()
e implementarSerializable
yComparable
.Para un resumen completo de todo lo que las enumeraciones tienen para ofrecer, recomiendo la cuarta edición de Thinking in Java de Bruce Eckel, que dedica un capítulo completo al tema. Particularmente ilustrativos son los ejemplos que involucran un juego de Rock, Paper, Scissors (es decir, RoShamBo) como enumeraciones.
fuente
De Java documentos -
Un ejemplo común es reemplazar una clase con un conjunto de constantes int finales estáticas privadas (dentro de un número razonable de constantes) con un tipo de enumeración. Básicamente, si crees que conoces todos los valores posibles de "algo" en tiempo de compilación, puedes representarlo como un tipo de enumeración. Las enumeraciones proporcionan legibilidad y flexibilidad sobre una clase con constantes.
Pocas otras ventajas que puedo pensar en tipos de enumeración. Siempre es una instancia de una clase de enumeración particular (de ahí el concepto de utilizar enumeraciones como singleton llega). Otra ventaja es que puede usar enumeraciones como un tipo en la declaración de cambio de caso. También puede usar toString () en la enumeración para imprimirlos como cadenas legibles.
fuente
DayOfWeek
enum ahora está predefinido, integrado en Java 8 y posterior como parte del marco java.time (y portado a Java 6 y 7 y a Android ).Puede usar una enumeración para representar un conjunto fijo de constantes más bien pequeño o un modo de clase interna mientras aumenta la legibilidad. Además, Enums puede imponer una cierta rigidez cuando se usa en los parámetros del método. Ofrecen la posibilidad interesante de pasar información a un constructor como en el ejemplo de Planetas en el sitio de Oracle y, como descubrió, también permiten una forma sencilla de crear un patrón singleton.
ej .:
Locale.setDefault(Locale.US)
lee mejorLocale.setDefault(1)
y exige el uso del conjunto fijo de valores que se muestran en un IDE cuando agrega el.
separador en lugar de todos los enteros.fuente
Enum
s enumerar un conjunto fijo de valores, de forma autodocumentada.Hacen que su código sea más explícito y también menos propenso a errores.
¿Por qué no usar
String
, oint
, en lugar deEnum
, constantes?if
) para asegurarse de que su argumento esté en el rango válido.String
s, de todos modos (esto depende de la complejidad delEnum
).Además, cada una de las
Enum
instancias es una clase, para la cual puede definir su comportamiento individual.Además, garantizan la seguridad de los subprocesos al crear las instancias (cuando se carga la enumeración), lo que ha sido de gran utilidad para simplificar el patrón Singleton .
Este blog ilustra algunas de sus aplicaciones, como una máquina de estado para un analizador.
fuente
Es útil saber que
enums
son como las otras clases conConstant
campos y aprivate constructor
.Por ejemplo,
El compilador lo compila de la siguiente manera;
fuente
enum
significa enumeración, es decir, mencionar (varias cosas) una por una.O
Por ejemplo:
Ventajas de enum:
por mas
fuente
¿Qué es una enumeración?
Por qué usar enum
Nota
fuente
Aparte de todo lo dicho por otros. En un proyecto anterior para el que solía trabajar, mucha comunicación entre entidades (aplicaciones independientes) estaba usando números enteros que representaban un pequeño conjunto. Fue útil declarar el conjunto como
enum
con métodos estáticos para obtenerenum
objetosvalue
y viceversa. El código parecía más limpio, usabilidad de mayúsculas y minúsculas y escritura más fácil en los registros.Crear
enum
objeto a partir de valores recibidos (por ejemplo, 1,2)ProtocolType.fromInt(2)
Escribir en registros usandomyEnumObj.name
Espero que esto ayude.
fuente
Enum hereda todos los métodos de
Object
clase y clase abstractaEnum
. Por lo tanto, puede usar sus métodos de reflexión, subprocesamiento múltiple, serilización, comparables, etc. Si solo declara una constante estática en lugar de Enum, no puede. Además de eso, el valor de Enum también se puede pasar a la capa DAO.Aquí hay un programa de ejemplo para demostrar.
fuente
ENum significa "Tipo enumerado". Es un tipo de datos que tiene un conjunto fijo de constantes que usted define.
fuente
En mi opinión, todas las respuestas que obtuviste hasta ahora son válidas, pero en mi experiencia, lo expresaría en pocas palabras:
Use enumeraciones si desea que el compilador verifique la validez del valor de un identificador.
De lo contrario, puede usar cadenas como siempre lo hizo (probablemente definió algunas "convenciones" para su aplicación) y será muy flexible ... pero no obtendrá 100% de seguridad contra los errores tipográficos en sus cadenas y se dará cuenta solo de ellas en tiempo de ejecución.
fuente
Use enumeraciones para TYPE SAFETY, esta es una función de idioma, por lo que generalmente obtendrá:
Las enumeraciones pueden tener métodos, constructores, incluso puede utilizar enumeraciones dentro de enumeraciones y combinar enumeraciones con interfaces.
Piense en las enumeraciones como tipos para reemplazar un conjunto bien definido de constantes int (que Java 'heredó' de C / C ++) y, en algunos casos, para reemplazar banderas de bits.
El libro Effective Java 2nd Edition tiene un capítulo completo sobre ellos y entra en más detalles. Consulte también esta publicación de desbordamiento de pila .
fuente
Java le permite restringir la variable a tener uno de los pocos valores predefinidos; en otras palabras, un valor de una lista enumerada. El uso
enums
puede ayudar a reducir los errores en su código. Aquí hay un ejemplo deenums
fuera de una clase:Esto restringe
coffeesize
a tener ya sea:BIG
,HUGE
oOVERWHELMING
como una variable.fuente
Enum? ¿Por qué debería ser usado? Creo que se entiende mejor cuándo lo usarás. Tengo la misma experiencia.
Supongamos que tiene una operación de creación, eliminación, edición y lectura de la base de datos.
Ahora, si crea una enumeración como una operación:
Ahora, puede declarar algo como:
Entonces puedes usarlo de muchas maneras. Siempre es bueno tener una enumeración para cosas específicas, ya que la operación de la base de datos en el ejemplo anterior se puede controlar comprobando la operación actual . Quizás se pueda decir que esto también se puede lograr con variables y valores enteros. Pero creo que Enum es más seguro y un programador.
Otra cosa: creo que todo programador ama el booleano , ¿no? Debido a que solo puede almacenar dos valores, dos valores específicos. Por lo tanto, se puede pensar que Enum tiene el mismo tipo de instalaciones donde un usuario definirá cuántos y qué tipo de valor almacenará, solo de una manera ligeramente diferente. :)
fuente
Hasta ahora, nunca he necesitado usar enumeraciones. He estado leyendo sobre ellos desde que se introdujeron en la versión 1.5 o versión del tigre, ya que se llamaba en su día. Nunca realmente resolvieron un 'problema' para mí. Para aquellos que lo usan (y veo que muchos lo hacen), estoy seguro de que definitivamente tiene algún propósito. Solo mis 2 libras.
fuente
Aquí hay muchas respuestas, solo quiero señalar dos específicas:
1) Uso como constantes en la
Switch-case
declaración. Switch case no le permitirá usar objetos String para case. Las enumeraciones son útiles. Más: http://www.javabeat.net/2009/02/how-to-use-enum-in-switch/2) Implementación
Singleton Design Pattern
- Enum nuevamente, viene a rescatar. Uso, aquí: ¿Cuál es el mejor enfoque para usar un Enum como un singleton en Java?fuente
Lo que me dio el momento Ah-Ha fue esta comprensión: que Enum tiene un constructor privado al que solo se puede acceder mediante la enumeración pública:
fuente
En cuanto a mí para que el código sea legible en el futuro, el siguiente caso de enumeración más útil se representa en el siguiente fragmento:
fuente
En mi experiencia, he visto que el uso de Enum a veces hace que los sistemas sean muy difíciles de cambiar. Si está utilizando una enumeración para un conjunto de valores específicos de dominio que cambian con frecuencia, y tiene muchas otras clases y componentes que dependen de él, es posible que desee considerar no usar un Enum.
Por ejemplo, un sistema de negociación que utiliza una Enum para mercados / intercambios. Hay muchos mercados por ahí y es casi seguro que habrá muchos subsistemas que necesitan acceder a esta lista de mercados. Cada vez que desee que se agregue un nuevo mercado a su sistema, o si desea eliminar un mercado, es posible que todo bajo el sol tenga que ser reconstruido y liberado.
Un mejor ejemplo sería algo así como un tipo de categoría de producto. Digamos que su software administra el inventario de una tienda por departamentos. Hay muchas categorías de productos y muchas razones por las que esta lista de categorías podría cambiar. Los gerentes pueden querer almacenar una nueva línea de productos, deshacerse de otras líneas de productos y posiblemente reorganizar las categorías de vez en cuando. Si tiene que reconstruir y volver a implementar todos sus sistemas simplemente porque los usuarios desean agregar una categoría de producto, entonces ha tomado algo que debería ser simple y rápido (agregar una categoría) y lo hizo muy difícil y lento.
En pocas palabras, las enumeraciones son buenas si los datos que representa son muy estáticos con el tiempo y tienen un número limitado de dependencias. Pero si los datos cambian mucho y tienen muchas dependencias, entonces necesita algo dinámico que no se verifique en el momento de la compilación (como una tabla de base de datos).
fuente
El singleton basado en enumeración
Este enfoque implementa el singleton aprovechando la garantía de Java de que cualquier valor enum se instancia solo una vez en un programa Java y enum proporciona soporte implícito para la seguridad de subprocesos. Dado que los valores de enumeración de Java son accesibles a nivel mundial, por lo tanto, se puede utilizar como singleton.
¿Como funciona esto? Bueno, la línea dos del código puede considerarse para algo como esto:
Y tenemos un buen singleton inicializado temprano.
Recuerde que, dado que se trata de una enumeración, siempre puede acceder a la instancia a través de
VentajasSingleton.INSTANCE
:valueOf
método se usa con el nombre deserializado para obtener la instancia deseada.Enum
clase java . La razón por la que la reflexión no se puede usar para crear instancias de objetos de tipo enum es porque la especificación java no lo permite y esa regla se codifica en la implementación delnewInstance
método de laConstructor
clase, que generalmente se usa para crear objetos a través de la reflexión:map
. En lugar de tener una sola instancia por aplicación (p. Ej., Eljava.lang.Runtime
), el patrón multitono garantiza una sola instancia por clave .Hay varias realizaciones del patrón singleton, cada una con ventajas y desventajas.
Descripción detallada de cada uno de ellos es demasiado detallado, así que acabo de poner un enlace a un buen artículo - Todo lo que quieres saber sobre Singleton
fuente
Usaría enumeraciones como un instrumento útil de mapeo, evitando múltiples
if-else
siempre que se implementen algunos métodos.Entonces el método
by(String label)
permite obtener el valor Enumerado por no enumerado. Además, uno puede inventar mapeo entre 2 enumeraciones. También podría intentar '1 a muchos' o 'muchos a muchos' además de la relación predeterminada 'uno a uno'Al final,
enum
es una clase Java. Por lo tanto, puede tener unmain
método dentro, que podría ser útil cuando necesite hacer algunas operaciones de mapeo deargs
inmediato.fuente
En lugar de hacer un montón de declaraciones constantes
Puedes agruparlos a todos en 1 enumeración
Entonces todo está organizado por el grupo común al que pertenecen
fuente
Las enumeraciones son como las clases. Al igual que la clase, también tiene métodos y atributos.
Las diferencias con la clase son: 1. las constantes enum son public, static, final. 2. una enumeración no puede usarse para crear un objeto y no puede extender otras clases. Pero puede implementar interfaces.
fuente
Además de @BradB Answer:
Eso es tan cierto ... Es extraño que sea la única respuesta que mencione eso. Cuando los principiantes descubren enumeraciones, lo toman rápidamente como un truco de magia para verificar el identificador válido para el compilador. Y cuando el código está destinado a ser utilizado en sistemas distribuidos, lloran ... un mes después. Mantener la compatibilidad con versiones anteriores que contenga una lista no estática de valores es una preocupación real y dolorosa. Esto se debe a que cuando agrega un valor a una enumeración existente, su tipo cambia (a pesar de que el nombre no lo hace).
"Ho, espera, puede parecer del mismo tipo, ¿verdad? Después de todo, son enumeraciones con el mismo nombre, ¿y no son enumeraciones enteras debajo del capó?" Y por estas razones, su compilador probablemente no marcará el uso de una definición del tipo en sí donde esperaba la otra. Pero, de hecho, son (en las formas más importantes) diferentes tipos. Lo más importante es que tienen diferentes dominios de datos, valores que son aceptables dado el tipo. Al agregar un valor, hemos cambiado efectivamente el tipo de la enumeración y, por lo tanto, rompemos la compatibilidad con versiones anteriores.
En conclusión: utilícelo cuando lo desee, pero, por favor, compruebe que el dominio de datos utilizado es un conjunto fijo finito, ya conocido .
fuente