java: Can == be used on enum?
Can ==
be used on enum
?
Yes: enums have tight instance controls that allows you to use ==
to compare instances. Here's the guarantee provided by the language specification:
JLS 8.9 Enums
An enum type has no instances other than those defined by its enum constants.
It is a compile-time error to attempt to explicitly instantiate an enum type. The
final clone
method inEnum
ensures thatenum
constants can never be cloned, and the special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types is prohibited. Together, these four things ensure that no instances of anenum
type exist beyond those defined by theenum
constants.Because there is only one instance of each
enum
constant, it is permissible to use the==
operator in place of theequals
method when comparing two object references if it is known that at least one of them refers to anenum
constant. (Theequals
method inEnum
is afinal
method that merely invokessuper.equals
on its argument and returns the result, thus performing an identity comparison.)
This guarantee is strong enough that Josh Bloch recommends, that if you insist on using the singleton pattern, the best way to implement it is to use a single-element enum
(see: Effective Java 2nd Edition, Item 3: Enforce the singleton property with a private constructor or an enum type; also Thread safety in Singleton)
What are the differences between ==
and equals
?
As a reminder, it needs to be said that generally, ==
is NOT a viable alternative to equals
. When it is, however (such as with enum
), there are two important differences to consider:
==
never throws NullPointerException
enum Color { BLACK, WHITE };
Color nothing = null;
if (nothing == Color.BLACK); // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException
==
is subject to type compatibility check at compile time
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!
Should ==
be used when applicable?
Bloch specifically mentions that immutable classes that have proper control over their instances can guarantee to their clients that ==
is usable. enum
is specifically mentioned to exemplify.
Item 1: Consider static factory methods instead of constructors
[...] it allows an immutable class to make the guarantee that no two equal instances exist:
a.equals(b)
if and only ifa==b
. If a class makes this guarantee, then its clients can use the==
operator instead of theequals(Object)
method, which may result in improved performance. Enum types provide this guarantee.
To summarize, the arguments for using ==
on enum
are:
- It works.
- It's faster.
- It's safer at run-time.
- It's safer at compile-time.