Alex Rivera | Logout

Is it OK to use == on enums in Java?

Asked 2009-02-10T19:59:01.313
121

Is it OK to use == on enums in Java, or do I need to use .equals()? In my testing, == always works, but I'm not sure if I'm guaranteed of that. In particular, there is no .clone() method on an enum, so I don't know if it is possible to get an enum for which .equals() would return a different value than ==.

For example, is this OK:

public int round(RoundingMode roundingMode) {
  if(roundingMode == RoundingMode.HALF_UP) {
    //do something
  } else if (roundingMode == RoundingMode.HALF_EVEN) {
    //do something
  }
  //etc
}

Or do I need to write it this way:

public int round(RoundingMode roundingMode) {
  if(roundingMode.equals(RoundingMode.HALF_UP)) {
    //do something
  } else if (roundingMode.equals(RoundingMode.HALF_EVEN)) {
    //do something
  }
  //etc
}
Edit
Report

3 Answers

13

Yes, it is as if you had created singleton instances for each value in the enum:

public abstract class RoundingMode {
  public static final RoundingMode HALF_UP = new RoundingMode();
  public static final RoundingMode HALF_EVEN = new RoundingMode();

  private RoundingMode() {
    // private scope prevents any subtypes outside of this class
  }
}

However, the enum construct gives you various benefits:

  • Each instance's toString() prints the name given in code.
  • (As mentioned in another post,) a variable of the enum type can be compared against constants using the switch-case control structure.
  • All the values in the enumeration can be queried using the values field that is 'generated' for each enum type
  • Here's the big one w.r.t identity comparisons: enum values survive serialization without cloning.

The serialization is a big gotchya. If I were to use the code above instead of an enum, here's how identity equality would behave:

RoundingMode original = RoundingMode.HALF_UP;
assert (RoundingMode.HALF_UP == original); // passes

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(original);
oos.flush();

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
RoundingMode deserialized = (RoundingMode) ois.readObject();

assert (RoundingMode.HALF_UP == deserialized); // fails
assert (RoundingMode.HALF_EVEN == deserialized); // fails

You can address this issue without enum, using a technique that involves writeReplace and readResolve, (see http://java.sun.com/j2se/1.4.2/docs/api/java/io/Serializable.html)...

I guess the point is -- Java goes

answered 2009-02-11T09:16:28.700
11

== compares the references of two objects. For enums, it is guaranteed that there will only be one instance, and therefore for any two enums that are the same, == will be true.

Reference:

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

(couldn't find anything in the Sun docs)

answered 2009-02-10T20:14:16.410
3

Enums are a great place to jam polymorphic code.

enum Rounding {
  ROUND_UP {
    public int round(double n) { ...; }
  },
  ROUND_DOWN {
    public int round(double n) { ...; }
  };

  public abstract int round(double n);
}

int foo(Rounding roundMethod) {
  return roundMethod.round(someCalculation());
}

int bar() {
  return foo(Rounding.ROUND_UP);
}
answered 2009-02-11T12:30:28.453

Your Answer