是否可以在Java中使用==枚举?

可以在Java中使用==枚举,还是需要使用.equals() ? 在我的testing中, ==总是起作用,但我不确定是否能保证。 特别是,在枚举上没有.clone()方法,所以我不知道是否有可能得到一个枚举,其中.equals()会返回一个不同于==值。

例如,这是OK的:

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

或者我需要这样写:

 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; } } 

是的,==很好 – 保证每个值都只有一个参考。

但是,有一个更好的方法来编写你的循环方法:

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

更好的方法是将函数放在枚举本身中,所以你可以调用roundingMode.round(someValue) 。 这到达Java枚举的核心 – 它们是面向对象的枚举,与其他地方的“命名值”不同。

编辑:规范不是很清楚,但第8.9节规定:

枚举types的主体可能包含枚举常量。 一个枚举常量定义了枚举types的一个实例。 一个枚举types除了由枚举常量定义的枚举types之外没有其他实例。

是的,就好像您为枚举中的每个值创build了单例实例:

公共抽象类RoundingMode {
   public static final RoundingMode HALF_UP = new RoundingMode();
   public static final RoundingMode HALF_EVEN = new RoundingMode();

  私人RoundingMode(){
     / /私人范围防止此类以外的任何子types
   }
 }

但是enum构造给你带来了各种好处:

  • 每个实例的toString()打印代码中给出的名称。
  • (如另一篇文章中提到的那样),可以使用switch-case控制结构将枚举types的variables与常量进行比较。
  • 枚举中的所有值都可以使用每个枚举types的“生成” values来查询
  • 以下是身份比较的重要内容:枚举值在没有克隆的情况下可以继续序列化。

序列化是一个很大的gotchya。 如果我要使用上面的代码而不是枚举,下面是身份相等的行为:

 RoundingMode original = RoundingMode.HALF_UP;
 assert(RoundingMode.HALF_UP == original);  //通过

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

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

 assert(RoundingMode.HALF_UP ==反序列化);  //失败
 assert(RoundingMode.HALF_EVEN ==反序列化);  //失败

可以解决此问题,而不枚举,使用涉及writeReplacereadResolve的技术(请参阅http://java.sun.com/j2se/1.4.2/docs/api/java/io/Serializable.html )…

我猜测的重点是 – Java不再允许您使用枚举值的身份来testing相等性; 这是一个鼓舞人心的做法。

==比较两个对象的引用。 对于枚举,保证只有一个实例,因此对于任何两个相同的枚举,==都是正确的。

参考:

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

(在Sun文档中找不到任何东西)

这里有一些你可能会感兴趣的邪恶代码。 :d

 public enum YesNo {YES, NO} public static void main(String... args) throws Exception { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); Unsafe unsafe = (Unsafe) field.get(null); YesNo yesNo = (YesNo) unsafe.allocateInstance(YesNo.class); Field name = Enum.class.getDeclaredField("name"); name.setAccessible(true); name.set(yesNo, "YES"); Field ordinal = Enum.class.getDeclaredField("ordinal"); ordinal.setAccessible(true); ordinal.set(yesNo, 0); System.out.println("yesNo " + yesNo); System.out.println("YesNo.YES.name().equals(yesNo.name()) "+YesNo.YES.name().equals(yesNo.name())); System.out.println("YesNo.YES.ordinal() == yesNo.ordinal() "+(YesNo.YES.ordinal() == yesNo.ordinal())); System.out.println("YesNo.YES.equals(yesNo) "+YesNo.YES.equals(yesNo)); System.out.println("YesNo.YES == yesNo " + (YesNo.YES == yesNo)); } 

枚举是堵塞多态代码的好地方。

 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); } 

请注意,通过RMI / IIOP传输枚举时存在问题。 看到这个线程:

http://www.velocityreviews.com/forums/t390342-enum-equality.html

==通常可以,并且==和.equals()都有优点。 我个人比较喜欢总是使用.equals()比较对象,包括enum 。 另见这个讨论:

比较Java枚举成员:==或equals()?