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

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

然而,我刚刚遇到一些使用equals运算符==而不是.equals()的代码:

public useEnums2(SomeEnum a)
{
    if(a == SomeEnum.SOME_ENUM_VALUE)
    {
        ...
    }
    ...
}

我应该使用哪个操作员?


当前回答

enums容易与==一起工作的原因是每个定义的实例也是一个单实例。因此,使用==进行身份比较总是有效的。

但使用==,因为它与枚举一起使用,意味着所有代码都与该枚举的使用紧密耦合。

例如:枚举可以实现接口。假设您当前正在使用实现Interface1的枚举。若稍后,有人将其更改或引入一个新的类Impl1作为同一接口的实现。然后,如果您开始使用Impl1的实例,由于前面使用了==,您将有很多代码需要更改和测试。

因此,除非有任何正当利益,否则最好遵循被视为良好的做法。

其他回答

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

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

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

这是一个被称为“从左侧比较常量”的最佳实践,您绝对应该遵循。

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

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

使用==以外的任何方法来比较枚举常量都是无稽之谈。这就像将类对象与equals进行比较——不要这样做!

然而,由于历史原因,Sun JDK 6u10和更早版本中存在一个令人讨厌的bug(BugId 6277781)。这个错误阻止了在反序列化的枚举上正确使用==,尽管这可以说是一种极端情况。

只有一件事可以补充所有其他优秀的答案。当您使用简单的lambda时,我更喜欢等于而不是==,因为您可以使用方法引用。

考虑以下lambdas:

Stream.of(SomeEnum.A, SomeEnum.B).anyMatch(e -> e == SomeEnum.B);
Stream.of(SomeEnum.A, SomeEnum.B).anyMatch(e -> e.equals(SomeEnum.B));

后者可以转换为:

Stream.of(SomeEnum.A, SomeEnum.B).anyMatch(SomeEnum.B::equals));

枚举是为公共静态final字段(不可变)声明的每个枚举常量返回一个实例(如单实例)的类,因此可以使用==运算符来检查它们的相等性,而不是使用equals()方法