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.
– Stuart RossiterOct 27 '15 at 13:02

2

Keep it simple. "==" is more readable and it works because enums are singleton by default. Ref
– lokeshAug 11 '18 at 16:06

Personally, I dont like 'null safety' mentioned as a reason to use ==.
– NivasNov 17 '09 at 18:13

229

@Nivas: why not? Do you like worrying about the order of your arguments (which only applies to comparing constants from the left, as in Pascal's answer)? Do you like always checking that a value is not null before .equals()ing it? I know I don't.
– Matt BallNov 17 '09 at 21:03

81

Keep in mind that when reading your code, the "==" may appear incorrect to the reader until he/she goes off and looks at the source for the type involved, then sees it's an enum. In that sense, it's less distracting to read ".equals()".
– Kevin BourrillionNov 18 '09 at 8:48

53

@Kevin - if you're not using an IDE that allows you to see types directly when viewing the source, you're cheating yourself - not an issue with a proper IDE.
– MetroidFan2002Nov 18 '09 at 15:26

56

Sometimes code gets refactored and it's possible that an enum gets replaced by a class, at which point == is no longer guaranteed to be correct, whereas equals continues to work seamlessly. For this reason, equals is clearly a better choice. If you want null safety (because you work on a code base which wasn't written so as to minimize the use of nulls), there's the Apache ObjectUtils or Guava's Objects#equal (or you can roll your own). I won't even mention the word "performance" for fear that someone rightfully slaps me with a Donald Knuth book.
– laszlokOct 7 '13 at 13:43

Can == be used on enum?

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:

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.

Nice answer but... 1. It works : agreed 2. it's faster : prove it for enums :) 3. It's safer at run-time : Color nothing = null; is IMHO a bug and should be fixed, your enum has two values, not three (see Tom Hawtin's comment) 4. It's safer at compile-time : OK, but equals would still return false. At the end, I don't buy it, I prefer equals() for the readability (see Kevin's comment).
– Pascal ThiventMay 30 '10 at 5:02

178

It's a black mark against Java that some people think that foo.equals(bar) is more readable than foo == bar
– Bennett McElweeJul 18 '12 at 5:20

19

It works: Until you need to replace an enum with a class as part of a refactoring. Good luck finding all the code using == that breaks. It's faster: Even if true (questionable), there's that Knuth quote about premature optimization. Safer at run-time: "Safe" is not the first word that springs to mind if the use of == is the only thing separating you from a NullPointerException. Safer at compile time: Not really. It can guard you from the rather elementary mistake of comparing the wrong types, but again, if that's how dumb your programmers are, "safe" is the one thing you're not.
– laszlokOct 7 '13 at 13:52

30

"if that's how dumb your programmers are, "safe" is the one thing you're not." -- I don't agree with this quote. This is what type checking is all about: preventing "dumb" mistakes at compile time, thus even before the code is run. Even smart people do dumb mistakes, better some guarantees than promises.
– ymajorosDec 12 '13 at 7:08

7

@laszlok: sure, but if things can fail, they just will. Having a fence for some dumb mistakes is always a good thing. There is plenty of room to be creative for less trivial bugs, let the compiler handle this one before you ever try to run your code.
– ymajorosFeb 19 '14 at 19:37

I do this when .equals()ing string values, but I still think that it's a crappy way to write null-safe code. I'd much rather have an operator (or a method, but I know that [null object].equals won't ever be null-safe in Java because of how the dot operator works) that's always null-safe, regardless of the order it's used in. Semantically, the "equals" operator should always commute.
– Matt BallNov 17 '09 at 20:48

2

Well, as Java doesn't have the Safe Navigation operator of Groovy (?.), I'll continue to use this practice when comparing to constants and, TBH, I don't find it crappy, maybe just less "natural".
– Pascal ThiventNov 17 '09 at 21:34

32

A null enum is typically an error. You've got this enumeration of all possible values, and here's another one!
– Tom Hawtin - tacklineNov 22 '09 at 21:00

7

Except for values that are explicitly annotated as @Nullable, I consider Compare Constants From The Left an antipattern because it spreads ambiguity about which values can or cannot be null. Enum types should almost never be @Nullable, so a null value would be a programming error; in such a case, the sooner you throw NPE, the more likely that you'll find your programming mistake where you allowed it to be null. So "best practice ... that you should definitely follow" is plain wrong when it comes to enum types.
– TobiasMay 22 '14 at 3:49

19

Compare Constants From The Left a best practice like Yoda style best English is.
– maaartinusSep 8 '14 at 11:51

As others have said, both == and .equals() work in most cases. The compile time certainty that you're not comparing completely different types of Objects that others have pointed out is valid and beneficial, however the particular kind of bug of comparing objects of two different compile time types would also be found by FindBugs (and probably by Eclipse/IntelliJ compile time inspections), so the Java compiler finding it doesn't add that much extra safety.

However:

The fact that == never throws NPE in my mind is a disadvantage of ==. There should hardly ever be a need for enum types to be null, since any extra state that you may want to express via null can just be added to the enum as an additional instance. If it is unexpectedly null, I'd rather have a NPE than == silently evaluating to false. Therefore I disagree with the it's safer at run-time opinion; it's better to get into the habit never to let enum values be @Nullable.

The argument that == is faster is also bogus. In most cases you'll call .equals() on a variable whose compile time type is the enum class, and in those cases the compiler can know that this is the same as == (because an enum's equals() method can not be overridden) and can optimize the function call away. I'm not sure if the compiler currently does this, but if it doesn't, and turns out to be a performance problem in Java overall, then I'd rather fix the compiler than have 100,000 Java programmers change their programming style to suit a particular compiler version's performance characteristics.

enums are Objects. For all other Object types the standard comparison is .equals(), not ==. I think it's dangerous to make an exception for enums because you might end up accidentally comparing Objects with == instead of equals(), especially if you refactor an enum into a non-enum class. In case of such a refactoring, the It works point from above is wrong. To convince yourself that a use of == is correct, you need to check whether value in question is either an enum or a primitive; if it was a non-enum class, it'd be wrong but easy to miss because the code would still compile. The only case when a use of .equals() would be wrong is if the values in question were primitives; in that case, the code wouldn't compile so it's much harder to miss. Hence, .equals() is much easier to identify as correct, and is safer against future refactorings.

I actually think that the Java language should have defined == on Objects to call .equals() on the left hand value, and introduce a separate operator for object identity, but that's not how Java was defined.

In summary, I still think the arguments are in favor of using .equals() for enum types.

Well, about point 3, I can use enum as a switch target so they're a bit special. Strings are a bit special too.
– CurtainDogSep 16 '14 at 1:56

The syntax for switch statements contains neither == nor .equals() so I don't see what your point is. My point 3.) is about how easy code is to verify for a reader. Switch statements' equality semantics are correct as long as the switch statement compiles.
– TobiasSep 24 '14 at 22:46

I suspect that compiler branch-prediction might make this test invalid. A smart compiler would recognize that both those if statements will always evaluate to false and thus avoid doing multiple compares. A really smart compiler might even recognize that the values in the y and x loops will have no effect on the outcome and optimize out the entire thing...
– Darrel HoffmanJun 22 '15 at 15:46

It could, but it definitely doesn't. I show the actual compiler-generated bytecode in my answer.
– ChrisCantrellJul 4 '15 at 14:07

you are both confused. :-) Branch prediction works at run-time so the different byte code is not super relevant. However, in this case branch prediction would help both cases equally.
– vidstigeAug 6 '15 at 6:33

6

Who cares? Unless you are comparing enums thousands of times inside a loop during a video game the extra nanosecond is meaningless.
– user949300Mar 12 '16 at 0:57

The bytecode is pretty irrelevant for the performance unless you're forcing interpreted mode. Write a JMH benchmark to see that the performance is exactly the same.
– maaartinusAug 31 '17 at 4:38

Other reason, in addition to the others already discussed here, is you could introduce a bug without realizing it. Suppose you have this enums which is exactly the same but in separated pacakges (it's not common, but it could happen):

However, there was a nasty bug (BugId 6277781) in Sun JDK 6u10 and earlier that might be interesting for historical reasons. This bug prevented proper use of == on deserialized enums, although this is arguably somewhat of a corner case.

Enums are classes that return one instance (like singletons) for each enumeration constant declared by public static final field (immutable) so that == operator could be used to check their equality rather than using equals() method

The reason enums work easily with == is because each defined instance is also a singleton. So identity comparison using == will always work.

But using == because it works with enums means all your code is tightly coupled with usage of that enum.

For example: Enums can implement an interface. Suppose you are currently using an enum which implements Interface1. If later on, someone changes it or introduces a new class Impl1 as an implementation of same interface. Then, if you start using instances of Impl1, you'll have a lot of code to change and test because of previous usage of ==.

Hence, it's best to follow what is deemed a good practice unless there is any justifiable gain.

Um. At that point, the question would be about whether you use == or equals on an interface. Plus all kinds of questions about whether it's really sensible to replace an implementation of an immutable type with a mutable implementation. And it's probably wise to figure out what good practice is before you worry about justifiable gain. (imho == is better practice).
– Robin DaviesDec 17 '18 at 10:21

Why is this solution any better than ==? With == you get NPE protection, easy-to-read code, and compile time type compatibility checking, and you get all of those without writing any custom equals-like methods.
– Matt BallOct 17 '14 at 14:51

1

An UNDEFINED value is probably a good idea. Of course, in Java 8 you would use an Optional instead.
– TomasOct 26 '15 at 20:41

The scope is rather clear on this question and primitive types are not in scope.
– TomDec 4 '18 at 12:02

@Tom the discussion going on here is misleading that == can never throw NPEs. This question has enough answers, but this can be a good reference in case someone like me who took 2 hours to get to bug/feature reads this.
– ayushgpDec 4 '18 at 12:07

1

I can't throw an NPE when you don't ignore the topic of this question. And even if you keep this answer here, do you think someone with the same issue you had would find this answer by search for something different? That person would need to search for enums they obviously don't use. This answer would make more sense on this question: stackoverflow.com/questions/7520432/…
– TomDec 4 '18 at 12:13

Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).