Pode ==ser usado enum?
Sim: as enumerações possuem controles de instância rígidos que permitem usar ==para comparar instâncias. Aqui está a garantia fornecida pela especificação de idioma (ênfase minha):
Um tipo de enumeração não possui instâncias diferentes daquelas definidas por suas constantes de enumeração.
É um erro em tempo de compilação tentar instanciar explicitamente um tipo de enum. O final clonemétodo Enumgarante que as enumconstantes nunca possam ser clonadas, e o tratamento especial pelo mecanismo de serialização garante que instâncias duplicadas nunca sejam criadas como resultado da desserialização. A instanciação reflexiva dos tipos de enum é proibida. Juntos, essas quatro coisas garantem que não enumexistam instâncias de um tipo além daquelas definidas pelas enumconstantes.
Como há apenas uma instância de cada enumconstante, é permitido usar o ==operador no lugar do equalsmétodo ao comparar duas referências de objeto, se for sabido que pelo menos uma delas se refere a uma enumconstante . (O equalsmétodo in Enumé um finalmétodo que apenas invoca super.equalsseu argumento e retorna o resultado, realizando uma comparação de identidade.)
Essa garantia é suficientemente forte que Josh Bloch recomenda que, se você insistir em usar o padrão singleton, a melhor maneira de implementá-lo é usar um elemento único enum(consulte: Java Efetivo 2ª Edição, Item 3: Aplicar a propriedade singleton com um construtor privado ou um tipo de enum ; também Segurança de threads em Singleton )
Quais são as diferenças entre ==e equals?
Como um lembrete, é preciso dizer que, geralmente, ==NÃO é uma alternativa viável equals. Quando é, no entanto (como com enum), há duas diferenças importantes a serem consideradas:
== nunca joga NullPointerException
enum Color { BLACK, WHITE };
Color nothing = null;
if (nothing == Color.BLACK); // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException
== está sujeito à verificação de compatibilidade de tipo em tempo de compilação
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!
Deve ==ser usado quando aplicável?
Bloch menciona especificamente que classes imutáveis que têm controle adequado sobre suas instâncias podem garantir a seus clientes que ==é utilizável. enumé especificamente mencionado para exemplificar.
Item 1: Considere métodos estáticos de fábrica em vez de construtores
[...] permite que uma classe imutável garanta que não existem duas instâncias iguais: a.equals(b)se e somente se a==b. Se uma classe faz essa garantia, seus clientes podem usar o ==operador em vez do equals(Object)método, o que pode resultar em melhor desempenho. Os tipos enum fornecem essa garantia.
Para resumir, os argumentos para usar ==on enumsão:
- Funciona.
- É mais rápido.
- É mais seguro em tempo de execução.
- É mais seguro em tempo de compilação.