Categories
enums java

Comparing Java enum members: == or equals()?

2024

I know that Java enums are compiled to classes with private constructors and a bunch of public static members. When comparing two members of a given enum, I’ve always used .equals(), e.g.

public useEnums(SomeEnum a)
{
    if(a.equals(SomeEnum.SOME_ENUM_VALUE))
    {
        ...
    }
    ...
}

However, I just came across some code that uses the equals operator == instead of .equals():

public useEnums2(SomeEnum a)
{
    if(a == SomeEnum.SOME_ENUM_VALUE)
    {
        ...
    }
    ...
}

Which operator is the one I should be using?

3

  • 7

    I just stumbled across a very similar question: stackoverflow.com/questions/533922/…

    – Matt Ball

    Dec 15, 2011 at 14:35

  • 56

    I’m surprised that in all the answers (especially the one from polygenelubricants which explains in detail why == works) that another big benefit of == wasn’t mentioned: that it makes explicit how enums work (as a fixed set of singleton objects). With equals it leads one to think that there can somehow be multiple instances of the same enum ‘alternative’ floating around.

    Oct 27, 2015 at 13:02

  • SomeEnum.SOME_ENUM_VALUE.equals(a) never throws NullPointerException while a.equals(SomeEnum.SOME_ENUM_VALUE) might.

    – Maarten

    Jul 6 at 9:00

1865

Both are technically correct. If you look at the source code for .equals(), it simply defers to ==.

I use ==, however, as that will be null safe.

1

  • 30

    another argument to use == instead of equals ist compile-time checking of types. myEnum.MY_CONSTANT.equals("Some String") will compile and myEnum.MY_CONSTANT == "Some String" will not, as "Some String" is not of the same type and the compiler can determin it upfront

    Jun 15, 2021 at 9:00


1271

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 (emphasis by me):

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 in Enum ensures that enum 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 an enum type exist beyond those defined by the enum constants.

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant. (The equals method in Enum is a final method that merely invokes super.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 if a==b. If a class makes this guarantee, then its clients can use the == operator instead of the equals(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.

0

    113

    Using == to compare two enum values works, because there is only one object for each enum constant.

    On a side note, there is actually no need to use == to write null-safe code, if you write your equals() like this:

    public useEnums(final SomeEnum a) {
        if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
            …
        }
        …
    }
    

    This is a best practice known as Compare Constants From The Left that you definitely should follow.

    2

    • 36

      A null enum is typically an error. You’ve got this enumeration of all possible values, and here’s another one!

      Nov 22, 2009 at 21:00

    • 34

      Compare Constants From The Left a best practice like Yoda style best English is.

      Sep 8, 2014 at 11:51