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

比较Java枚举成员:==或等于()?,java,enums,Java,Enums,我知道Java枚举被编译成带有私有构造函数和一堆公共静态成员的类。在比较给定枚举的两个成员时,我总是使用.equals(),例如 public useEnums(SomeEnum a) { if(a.equals(SomeEnum.SOME_ENUM_VALUE)) { ... } ... } 但是,我刚刚遇到一些使用equals运算符而不是.equals()的代码: 我应该使用哪个运算符?对于枚举,两者都是正确的 对于枚举,两者都是正确的 两者

我知道Java枚举被编译成带有私有构造函数和一堆公共静态成员的类。在比较给定枚举的两个成员时,我总是使用
.equals()
,例如

public useEnums(SomeEnum a)
{
    if(a.equals(SomeEnum.SOME_ENUM_VALUE))
    {
        ...
    }
    ...
}
但是,我刚刚遇到一些使用equals运算符而不是.equals()的代码:


我应该使用哪个运算符?

对于枚举,两者都是正确的

对于枚举,两者都是正确的

两者在技术上都是正确的。如果您查看
.equals()
的源代码,它只是遵从
=


但是,我使用
==
,因为这将是空安全的。

两者在技术上都是正确的。如果您查看
.equals()
的源代码,它只是遵从
=


但是,我使用
=
,因为这将是空安全的。

使用
=
比较两个枚举值是有效的,因为每个枚举常量只有一个对象

另一方面,如果您这样编写
equals()
,实际上不需要使用
==
来编写空安全代码:

public useEnums(final SomeEnum a) {
    if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
        …
    }
    …
}

这是一个众所周知的最佳实践,您绝对应该遵循。

使用
=
比较两个枚举值是有效的,因为每个枚举常量只有一个对象

另一方面,如果您这样编写
equals()
,实际上不需要使用
==
来编写空安全代码:

public useEnums(final SomeEnum a) {
    if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
        …
    }
    …
}
这是一个众所周知的最佳实践,您绝对应该遵循。

是否可以在
enum
上使用
=
? 是:枚举具有紧密的实例控件,允许您使用
==
来比较实例。以下是语言规范提供的保证(我强调):

枚举类型除了由其枚举常量定义的实例外,没有其他实例

尝试显式实例化枚举类型是编译时错误。
Enum
中的
final clone
方法确保永远不能克隆
Enum
常量,序列化机制的特殊处理确保永远不会由于反序列化而创建重复实例。禁止枚举类型的反射实例化。这四个因素共同确保
enum
类型的实例不存在于
enum
常量定义的实例之外

由于每个
枚举
常量只有一个实例,在比较两个对象引用时,如果已知其中至少有一个引用了
枚举
常量,则允许使用
=
操作符代替
等于
方法。(
Enum
中的
equals
方法是一个
final
方法,它仅对其参数调用
super.equals
,并返回结果,从而执行身份比较。)

Josh Bloch建议,如果您坚持使用singleton模式,实现它的最佳方法是使用单个元素
enum
(请参阅:Efficive Java第二版,第3项:使用私有构造函数或enum类型强制singleton属性;另外)


=
等于
之间有什么区别? 需要提醒的是,一般来说,
==
不是
等于
的可行替代方案。但是,如果是(例如使用
enum
),则需要考虑两个重要的区别:

=
从不抛出
NullPointerException
=
在编译时接受类型兼容性检查
如果适用,是否应使用
==
? Bloch特别提到,对其实例进行适当控制的不可变类可以向其客户机保证
=
是可用的<代码>枚举是特别提到的示例

项目1:考虑静态工厂方法,而不考虑构造函数< /P> […]它允许不可变类保证不存在两个相等的实例:

a.equals(b)
当且仅当
a==b
时。如果一个类保证了这一点,那么它的客户端可以使用
=
操作符而不是
equals(Object)
方法,这可能会提高性能。枚举类型提供了这种保证

总之,在
enum
上使用
=
的参数如下:

  • 它起作用了
  • 它更快
  • 它在运行时更安全
  • 它在编译时更安全
是否可以在
枚举上使用
==
? 是:枚举具有紧密的实例控件,允许您使用
==
来比较实例。以下是语言规范提供的保证(我强调):

枚举类型除了由其枚举常量定义的实例外,没有其他实例

尝试显式实例化枚举类型是编译时错误。
Enum
中的
final clone
方法确保永远不能克隆
Enum
常量,序列化机制的特殊处理确保永远不会由于反序列化而创建重复实例。禁止枚举类型的反射实例化。这四个因素共同确保
enum
类型的实例不存在于
enum
常量定义的实例之外

由于每个
枚举
常量只有一个实例,在比较两个对象引用时,如果已知其中至少有一个引用了
枚举
常量,则允许使用
=
操作符代替
等于
方法。(
Enum
中的
equals
方法是一个
final
方法,它仅在参数和参数上调用
super.equals
enum Color { BLACK, WHITE };

Color nothing = null;
if (nothing == Color.BLACK);      // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException
enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };

if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine
if (Color.BLACK == Chiral.LEFT);      // DOESN'T COMPILE!!! Incompatible types!
import java.util.Date;

public class EnumCompareSpeedTest {

    static enum TestEnum {ONE, TWO, THREE }

    public static void main(String [] args) {

        Date before = new Date();
        int c = 0;

        for(int y=0;y<5;++y) {
            for(int x=0;x<Integer.MAX_VALUE;++x) {
                if(TestEnum.ONE.equals(TestEnum.TWO)) {++c;}
                if(TestEnum.ONE == TestEnum.TWO){++c;}              
            }
        }

        System.out.println(new Date().getTime() - before.getTime());
    }   

}
 21  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 24  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 27  invokevirtual EnumCompareSpeedTest$TestEnum.equals(java.lang.Object) : boolean [28]
 30  ifeq 36

 36  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 39  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 42  if_acmpne 48
public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable
package first.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}
package second.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}
import second.pckg.Category;
...

Category.JAZZ.equals(item.getCategory())
import second.pckg.Category; 
...

Category.JAZZ == item.getCategory() 
Objects.equals( thisEnum , thatEnum )
boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ;  // Returns `false`.
return 
    ( a == b ) 
    || 
    ( 
        a != null 
        && 
        a.equals( b )
    )
;