Se ==
puede utilizar en enum
?
Sí: las enumeraciones tienen controles de instancia ajustados que le permiten usar ==
para comparar instancias. Aquí está la garantía proporcionada por la especificación del idioma (énfasis por mí):
Un tipo de enumeración no tiene instancias distintas de las definidas por sus constantes de enumeración.
Es un error en tiempo de compilación intentar crear una instancia explícita de un tipo de enumeración. El final clone
método Enum
asegura que las enum
constantes nunca se puedan clonar, y el tratamiento especial por el mecanismo de serialización asegura que nunca se creen instancias duplicadas como resultado de la deserialización. Se prohíbe la creación de instancias reflexivas de tipos de enumeración. Juntas, estas cuatro cosas aseguran que no existan instancias de un enum
tipo más allá de las definidas por las enum
constantes.
Debido a que solo hay una instancia de cada enum
constante, está permitido usar el ==
operador en lugar del equals
método al comparar dos referencias de objeto si se sabe que al menos una de ellas se refiere a una enum
constante . (El equals
método en Enum
es un final
método que simplemente invoca super.equals
su argumento y devuelve el resultado, realizando así una comparación de identidad).
Esta garantía es lo suficientemente sólida como para que Josh Bloch recomiende que, si insiste en usar el patrón singleton, la mejor manera de implementarlo es usar un elemento único enum
(consulte: Java 2nd Edition, elemento 3: aplicar la propiedad singleton con un constructor privado o un tipo de enumeración ; también seguridad de subprocesos en Singleton )
¿Cuáles son las diferencias entre ==
y equals
?
Como recordatorio, hay que decir que, en general, ==
NO es una alternativa viable para equals
. Sin embargo, cuando es así (como con enum
), hay dos diferencias importantes a considerar:
==
nunca tira NullPointerException
enum Color { BLACK, WHITE };
Color nothing = null;
if (nothing == Color.BLACK); // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException
==
está sujeto a verificación de compatibilidad de tipos en tiempo de compilación
enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };
if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine
if (Color.BLACK == Chiral.LEFT); // DOESN'T COMPILE!!! Incompatible types!
¿Debe ==
usarse cuando corresponda?
Bloch menciona específicamente que las clases inmutables que tienen un control adecuado sobre sus instancias pueden garantizar a sus clientes que ==
es utilizable. enum
se menciona específicamente para ejemplificar.
Elemento 1: Considere métodos de fábrica estáticos en lugar de constructores
[...] permite que una clase inmutable garantice que no existen dos instancias iguales: a.equals(b)
si y solo si a==b
. Si una clase hace esta garantía, sus clientes pueden usar el ==
operador en lugar del equals(Object)
método, lo que puede mejorar el rendimiento. Los tipos de enumeración proporcionan esta garantía.
Para resumir, los argumentos para usar ==
en enum
son:
- Funciona.
- Es mas rapido.
- Es más seguro en tiempo de ejecución.
- Es más seguro en tiempo de compilación.