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 clonemétodo Enumasegura que las enumconstantes 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 enumtipo más allá de las definidas por las enumconstantes.
Debido a que solo hay una instancia de cada enumconstante, está permitido usar el ==operador en lugar del equalsmétodo al comparar dos referencias de objeto si se sabe que al menos una de ellas se refiere a una enumconstante . (El equalsmétodo en Enumes un finalmétodo que simplemente invoca super.equalssu 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. enumse 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 enumson:
- Funciona.
- Es mas rapido.
- Es más seguro en tiempo de ejecución.
- Es más seguro en tiempo de compilación.