可以==
在Java中使用枚举,还是需要使用.equals()
?在我的测试中,==
总是有效,但我不确定我是否能保证这一点.特别是,.clone()
枚举上没有方法,所以我不知道是否有可能得到一个枚举,其.equals()
返回的值不同于==
.
例如,这样就可以了:
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 }
Varkhan.. 145
只需我2美分:这是由Sun发布的Enum.java的代码,也是JDK的一部分:
public abstract class Enum> implements Comparable , 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; } }
谢谢!我想如果我刚想到用编译器进入.equals()我会看到这个...... (4认同)
Jon Skeet.. 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枚举的核心 - 它们是面向对象的枚举,与其他地方的"命名值"不同.
编辑:规范不是很清楚,但第8.9节规定:
枚举类型的主体可能包含枚举常量.枚举常量定义枚举类型的实例.枚举类型没有除其枚举常量定义的实例之外的实例.
哦 - 你怀疑Jon Skeet?你没有在这里很久;) (2认同)
Dilum Ranatu.. 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
构造为您提供了各种好处:
每个实例的toString()都打印代码中给出的名称.
(如另一篇文章中所述),可以使用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不遗余力地允许你使用枚举值的身份来测试相等性; 这是一种鼓励的做法.
只需我2美分:这是由Sun发布的Enum.java的代码,也是JDK的一部分:
public abstract class Enum> implements Comparable , 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节规定:
枚举类型的主体可能包含枚举常量.枚举常量定义枚举类型的实例.枚举类型没有除其枚举常量定义的实例之外的实例.
是的,就好像你为枚举中的每个值创建了单例实例:
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
构造为您提供了各种好处:
每个实例的toString()都打印代码中给出的名称.
(如另一篇文章中所述),可以使用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不遗余力地允许你使用枚举值的身份来测试相等性; 这是一种鼓励的做法.
==比较两个对象的引用.对于枚举,保证只有一个实例,因此对于任何两个相同的枚举,==将为真.
参考:
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)); }