是否可以在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 ==反序列化); //失败
您可以解决此问题,而不枚举,使用涉及writeReplace
和readResolve
的技术(请参阅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()?