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

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
}

我的2美分:这是Sun公司发布的Enum.java代码,也是JDK的一部分:

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {

    // [...]

    /**
     * Returns true if the specified object is equal to this
     * enum constant.
     *
     * @param other the object to be compared for equality with this object.
     * @return  true if the specified object is equal to this
     *          enum constant.
     */
    public final boolean equals(Object other) { 
        return this==other;
    }


}

Yes, == is fine - there's guaranteed to be just a single reference for each value.

However, there's a better way of writing your round method:

public int round(RoundingMode roundingMode) {
  switch (roundingMode) {
    case HALF_UP:
       //do something
       break;
    case HALF_EVEN:
       //do something
       break;
    // etc
  }
}

An even better way of doing it is to put the functionality within the enum itself, so you could just call roundingMode.round(someValue) . This gets to the heart of Java enums - they're object-oriented enums, unlike the "named values" found elsewhere.

EDIT: The spec isn't very clear, but section 8.9 states:

The body of an enum type may contain enum constants. An enum constant defines an instance of the enum type. An enum type has no instances other than those defined by its enum constants.


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 wrt 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 out of its way to allow you use enum values' identities for testing equality; it is an encouraged practice.

    链接地址: http://www.djcxy.com/p/16334.html

    上一篇: 单线程中的线程安全

    下一篇: 在Java的枚举中使用==可以吗?