Estoy muy familiarizado con C # pero estoy empezando a trabajar más en Java. Esperaba aprender que las enumeraciones en Java eran básicamente equivalentes a las de C #, pero aparentemente este no es el caso. Inicialmente, me entusiasmó saber que las enumeraciones de Java podrían contener múltiples datos que parecen muy ventajosos ( http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ). Sin embargo, desde entonces he descubierto que faltan muchas características que son triviales en C #, como la capacidad de asignar fácilmente un determinado elemento a un cierto valor y, en consecuencia, la capacidad de convertir un número entero en una enumeración sin una cantidad decente de esfuerzo ( es decir, convertir el valor entero en Java Enum correspondiente ).
Entonces mi pregunta es esta: ¿hay algún beneficio para las enumeraciones de Java sobre una clase con un montón de campos finales estáticos públicos? ¿O simplemente proporciona una sintaxis más compacta?
EDITAR: Déjame ser más claro. ¿Cuál es el beneficio de las enumeraciones Java sobre una clase con un montón de campos finales estáticos públicos del mismo tipo ? Por ejemplo, en el ejemplo de los planetas en el primer enlace, ¿cuál es la ventaja de una enumeración sobre una clase con estas constantes públicas:
public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
Por lo que puedo decir, la respuesta de casablanca es la única que satisface esto.
public static final
campos, que pueden ser valores escritos y no necesariamenteint
s.S
, por lo que ahora estamos hablando de pasarlos probablemente a funciones, etc. ¿ Necesitamos seguridad de tipografía? Bueno, no, pero la mayoría de las personas consideran los tipos de estilo c de "todo es unvoid*
" buen estilo y puede detener los errores (¡especialmente si pasa más de un parámetro enum / string!). También pone las constantes en su propio espacio de nombres, etc. Contrariamente a eso, no hay una ventaja real de tener variables simples.int
s, no hay seguridad de tipo porque uno podría pasar cualquier valor. Los objetos mecanografiados, por otro lado, no son diferentes de las enumeraciones en términos de seguridad de tipos.Respuestas:
Técnicamente, uno podría ver las enumeraciones como una clase con un montón de constantes escritas, y de hecho así es como las constantes de enumeración se implementan internamente. El uso de un
enum
embargo le da métodos útiles ( Enum javadoc ) que de otra manera tendrían que aplicar a sí mismo, como por ejemploEnum.valueOf
.fuente
.values()
que iterar sobre la lista de valores.switch
declaraciones decase
declaraciones sin calificación.ordinal().
EnumSet
yEnumMap
clases.fuente
switch
declaraciones que fueron la motivación original para usar unEnum
.Nadie mencionó la capacidad de usarlos en
switch
declaraciones; Voy a tirar eso también.Esto permite que las enumeraciones complejas arbitrariamente se usen de manera limpia sin usar secuencias
instanceof
potencialmente confusasif
o valores de conmutación no string / int. El ejemplo canónico es una máquina de estados.fuente
La principal ventaja es la seguridad de tipo. Con un conjunto de constantes, cualquier valor del mismo tipo intrínseco podría usarse, introduciendo errores. Con una enumeración solo se pueden usar los valores aplicables.
Por ejemplo
vs
fuente
setSize(null)
a su segundo ejemplo, pero es probable que falle mucho antes que el error del primer ejemplo.Hay menos confusión. Tomar
Font
por ejemplo. Tiene un constructor que toma el nombre delFont
que deseas, su tamaño y su estilo (new Font(String, int, int)
). Hasta el día de hoy no puedo recordar si el estilo o el tamaño van primero. SiFont
había utilizado unaenum
para todos sus diferentes estilos (PLAIN
,BOLD
,ITALIC
,BOLD_ITALIC
), su constructor se vería asíFont(String, Style, int)
, evitando cualquier confusión. Desafortunadamente,enum
no existían cuandoFont
se creó la clase, y dado que Java debe mantener la compatibilidad inversa, esta ambigüedad siempre nos afectará.Por supuesto, esto es solo un argumento para usar un en
enum
lugar depublic static final
constantes. Las enumeraciones también son perfectas para los singletons y la implementación del comportamiento predeterminado al tiempo que permiten una personalización posterior (es decir, el patrón de estrategia ). Un ejemplo de esto último esjava.nio.file
'sOpenOption
yStandardOpenOption
: si un desarrollador quería crear su propia no estándarOpenOption
, lo que pudo.fuente
enum
sin usar varargs o aSet
para tomar un número arbitrario de ellos.interface Foo { public void bar(String baz); }
. Alguien hace una clase que invocabar
:someFoo.bar(baz = "hello");
. Cambio la firma deFoo::bar
apublic void bar(String foobar)
. Ahora, la persona que llamósomeFoo
deberá modificar su código si todavía quiere que funcione.Aquí hay muchas buenas respuestas, pero ninguna menciona que hay implementaciones altamente optimizadas de las clases / interfaces API de la colección específicamente para enumeraciones :
Estas clases específicas de enumeración solo aceptan
Enum
instancias (lasEnumMap
únicas solo aceptanEnum
s como claves), y siempre que sea posible, vuelven a la representación compacta y la manipulación de bits en su implementación.¿Qué significa esto?
Si nuestro
Enum
tipo no tiene más de 64 elementos (la mayoría de losEnum
ejemplos de la vida real calificarán para esto), las implementaciones almacenan los elementos en un sololong
valor, cadaEnum
instancia en cuestión se asociará con un poco de esta longitud de 64 bitslong
. Agregar un elemento a unEnumSet
es simplemente establecer el bit apropiado en 1, eliminarlo es solo establecer ese bit en 0. ¡Probar si un elemento está en elSet
es solo una prueba de máscara de bits! ¡Ahora tienes que amarEnum
por esto!fuente
What does this mean?
sección. Sabía que había una división en la implementación en el tamaño 64, pero en realidad no sabía por quéejemplo:
Limitación de las constantes de Java
1) Sin seguridad de tipo : en primer lugar, no es de tipo seguro; puede asignar cualquier valor int válido a int, por ejemplo, 99, aunque no hay una moneda para representar ese valor.
2) Sin impresión significativa : el valor de impresión de cualquiera de estas constantes imprimirá su valor numérico en lugar del nombre significativo de la moneda, por ejemplo, cuando imprima NICKLE imprimirá "5" en lugar de "NICKLE"
3) Sin espacio de nombres : para acceder a la constante currencyDenom necesitamos prefijar el nombre de la clase, por ejemplo, CurrencyDenom.PENNY en lugar de simplemente usar PENNY, aunque esto también se puede lograr mediante la importación estática en JDK 1.5
Ventaja de enum
1) Las enumeraciones en Java son de tipo seguro y tienen su propio espacio de nombres. Significa que su enumeración tendrá un tipo, por ejemplo, "Moneda" en el siguiente ejemplo y no puede asignar ningún valor que no sea el especificado en Constantes de enumeración.
Currency coin = Currency.PENNY; coin = 1; //compilation error
2) Enum en Java son tipos de referencia como clase o interfaz y puede definir constructor, métodos y variables dentro de Java Enum, lo que lo hace más poderoso que Enum en C y C ++ como se muestra en el siguiente ejemplo de tipo Java Enum.
3) Puede especificar valores de constantes enum en el momento de la creación como se muestra en el siguiente ejemplo: public enum Currency {PENNY (1), NICKLE (5), DIME (10), QUARTER (25)}; Pero para que esto funcione, debe definir una variable miembro y un constructor porque PENNY (1) en realidad está llamando a un constructor que acepta el valor int, vea el siguiente ejemplo.
Referencia: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html
fuente
El primer beneficio de las enumeraciones, como ya ha notado, es la simplicidad de sintaxis. Pero el punto principal de las enumeraciones es proporcionar un conjunto conocido de constantes que, por defecto, forman un rango y ayudan a realizar un análisis de código más completo a través de verificaciones de seguridad de tipo y valor.
Esos atributos de las enumeraciones ayudan tanto a un programador como a un compilador. Por ejemplo, supongamos que ve una función que acepta un número entero. ¿Qué podría significar ese entero? ¿Qué tipo de valores puedes pasar? Realmente no lo sabes de inmediato. Pero si ve una función que acepta enum, conoce muy bien todos los valores posibles que puede pasar.
Para el compilador, las enumeraciones ayudan a determinar un rango de valores y, a menos que asigne valores especiales a los miembros de enumeración, son rangos bien desde 0 en adelante. Esto ayuda a localizar automáticamente errores en el código a través de verificaciones de seguridad de tipo y más. Por ejemplo, el compilador puede advertirle que no maneja todos los valores de enumeración posibles en su declaración de cambio (es decir, cuando no tiene
default
mayúsculas y minúsculas y maneja solo uno de los N valores de enumeración). También le advierte cuando convierte un entero arbitrario en enum porque el rango de valores de enum es menor que el entero y eso a su vez puede provocar errores en la función que realmente no acepta un entero. Además, generar una tabla de salto para el interruptor se vuelve más fácil cuando los valores son de 0 en adelante.Esto no solo es cierto para Java, sino también para otros lenguajes con una estricta verificación de tipos. C, C ++, D, C # son buenos ejemplos.
fuente
Una enumeración es implícitamente final, con unos constructores privados, todos sus valores son del mismo tipo o un subtipo, puede obtener todos sus valores usando
values()
, obtiene suname()
oordinal()
valor o puede buscar una enumeración en número o nombre.También puede definir subclases (aunque no sea final, algo que no puede hacer de otra manera)
fuente
enum Beneficios:
"como la capacidad de asignar fácilmente un cierto valor a un elemento enum"
"y, en consecuencia, la capacidad de convertir un número entero en una enumeración sin una cantidad decente de esfuerzo" Agregue un método que convierta int a enumeración que hace eso. Simplemente agregue HashMap estático <Integer, EnumX> que contiene la enumeración java de mapeo .
Si realmente desea convertir ord = VAL_200.ordinal () de nuevo a val_200 simplemente use: EnumX.values () [ord]
fuente
Otra diferencia importante es que el compilador de Java trata los
static final
campos de tipos primitivos y String como literales. Significa que estas constantes se vuelven en línea. Es similar alC/C++
#define
preprocesador. Ver esta pregunta SO . Este no es el caso con las enumeraciones.fuente
Obtiene la comprobación en tiempo de compilación de valores válidos cuando utiliza una enumeración. Mira esta pregunta.
fuente
La mayor ventaja es que los Singleton de enum son fáciles de escribir y seguros para subprocesos:
y
ambos son similares y manejó la serialización por sí mismos mediante la implementación
más
fuente
Creo que un
enum
no puede serfinal
, porque debajo del capó el compilador genera subclases para cadaenum
entrada.Más información de la fuente
fuente
Hay muchas ventajas de las enumeraciones que se publican aquí, y estoy creando tales enumeraciones en este momento como se pregunta en la pregunta. Pero tengo una enumeración con 5-6 campos.
En este tipo de casos, cuando tiene múltiples campos en enumeraciones, es mucho más difícil entender qué valor pertenece a cada campo, ya que necesita ver el constructor y el globo ocular.
La clase con
static final
constantes y el uso deBuilder
patrones para crear dichos objetos lo hacen más legible. Pero, perdería todas las demás ventajas de usar una enumeración, si las necesita. Una desventaja de este tipo de clases es, es necesario agregar losPlanet
objetos manualmente a lalist/set
dePlanets.
Yo prefiero enumeración sobre dicha clase, que
values()
viene muy bien y nunca se sabe si los necesita para su uso enswitch
oEnumSet
oEnumMap
en el futuro :)fuente
Razón principal: las enumeraciones lo ayudan a escribir código bien estructurado donde el significado semántico de los parámetros es claro y fuertemente tipado en tiempo de compilación, por todas las razones que otras respuestas han dado.
Quid pro quo: en Java, la variedad de miembros de Enum es definitiva. Eso normalmente es bueno, ya que ayuda a valorar la seguridad y las pruebas, pero en algunas situaciones podría ser un inconveniente, por ejemplo, si está extendiendo el código base existente quizás desde una biblioteca. Por el contrario, si los mismos datos están en una clase con campos estáticos, puede agregar fácilmente nuevas instancias de esa clase en tiempo de ejecución (es posible que también necesite escribir código para agregarlos a cualquier Iterable que tenga para esa clase). Pero este comportamiento de Enums se puede cambiar: usando la reflexión puede agregar nuevos miembros en tiempo de ejecución o reemplazar miembros existentes, aunque esto probablemente solo se debe hacer en situaciones especializadas donde no hay alternativa: es decir, es una solución extravagante y puede producir problemas inesperados, mira mi respuesta en¿Puedo agregar y eliminar elementos de enumeración en tiempo de ejecución en Java ?
fuente