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

Viewed 914315

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?

15 Answers

tl;dr

Another option is the Objects.equals utility method.

Objects.equals( thisEnum , thatEnum )

Objects.equals for null-safety

equals operator == instead of .equals()

Which operator is the one I should be using?

A third option is the static equals method found on the Objects utility class added to Java 7 and later.

Example

Here’s an example using the Month enum.

boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ;  // Returns `false`.

Benefits

I find a couple benefits to this method:

  • Null-safety
  • Compact, readable

How it works

What is the logic used by Objects.equals?

See for yourself, from the Java 10 source code of OpenJDK:

return 
    ( a == b ) 
    || 
    ( 
        a != null 
        && 
        a.equals( b )
    )
;

One of the Sonar rules is Enum values should be compared with "==". The reasons are as follows:

Testing equality of an enum value with equals() is perfectly valid because an enum is an Object and every Java developer knows == should not be used to compare the content of an Object. At the same time, using == on enums:

  • provides the same expected comparison (content) as equals()

  • is more null-safe than equals()

  • provides compile-time (static) checking rather than runtime checking

For these reasons, use of == should be preferred to equals().

Last but not least, the == on enums is arguably more readable (less verbose) than equals().

Just one thing to add to all the other excellent answers. When you use a simple lambda I do prefer equals over ==, because you can use method referencing.

Consider following lambdas:

Stream.of(SomeEnum.A, SomeEnum.B).anyMatch(e -> e == SomeEnum.B);
Stream.of(SomeEnum.A, SomeEnum.B).anyMatch(e -> e.equals(SomeEnum.B));

The later can be converted to:

Stream.of(SomeEnum.A, SomeEnum.B).anyMatch(SomeEnum.B::equals));
Related