在Java中的枚举上使用==
是否可以,或者我是否需要使用.equals()
?在我的测试中,==
始终有效,但我不确定我是否能保证这一点。特别是,枚举上没有.clone()
方法,因此我不知道是否有可能获得枚举.equals()
将返回与==
不同的值。< / p>
例如,这样就可以了:
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
}
答案 0 :(得分:142)
只需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;
}
}
答案 1 :(得分:76)
是的,==很好 - 保证每个值只有一个参考。
然而,有一种更好的方法来编写圆形方法:
public int round(RoundingMode roundingMode) {
switch (roundingMode) {
case HALF_UP:
//do something
break;
case HALF_EVEN:
//do something
break;
// etc
}
}
甚至更好的方法是将功能放在枚举本身中,这样你就可以调用roundingMode.round(someValue)
。这是Java枚举的核心 - 它们是面向对象的枚举,与其他地方的“命名值”不同。
编辑:规范不是很清楚,但section 8.9表示:
枚举类型的主体可能包含 枚举常量。枚举常数 定义枚举类型的实例。 枚举类型没有其他实例 比它的枚举定义的那些 常数。
答案 2 :(得分:13)
是的,就好像你为枚举中的每个值创建了单例实例:
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 } }
然而,enum
结构为您提供了各种好处:
switch-case
控件结构将枚举类型的变量与常量进行比较。values
字段查询枚举中的所有值序列化是一个很大的问题。如果我使用上面的代码而不是枚举,这就是身份相等的行为方式:
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
你 可以使用涉及writeReplace
和readResolve
的技术(请参阅http://java.sun.com/j2se/1.4.2/docs/api/java/io/Serializable.html)而无需枚举来解决此问题...
我想重点是 - Java不遗余力地允许你使用枚举值的身份来测试相等性;这是一种鼓励的做法。
答案 3 :(得分:10)
==比较两个对象的引用。对于枚举,保证只有一个实例,因此对于任何两个相同的枚举,==将为真。
参考:
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
(在Sun文档中找不到任何内容)
答案 4 :(得分:6)
这是一些你可能会感兴趣的恶意代码。 :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));
}
答案 5 :(得分:3)
枚举是阻止多态代码的好地方。
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);
}
答案 6 :(得分:1)
请注意,通过RMI / IIOP传输枚举时会出现问题。见这个主题:
http://www.velocityreviews.com/forums/t390342-enum-equality.html
答案 7 :(得分:1)
==通常没问题,并且==和.equals()
都有优势。我个人更喜欢在比较对象时始终使用.equals()
,包括enum
。另见讨论: