我知道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)
    {
        ...
    }
    ...
}

我应该使用哪个操作员?


当前回答

简而言之,两者都有利弊。

一方面,如其他答案所述,使用==具有优势。

另一方面,如果出于任何原因使用不同的方法(普通类实例)替换enum,那么使用==会使您受到攻击。(待定)

其他回答

tl;博士

另一个选项是Objects.equals实用程序方法。

Objects.equals( thisEnum , thatEnum )

Objects.equals表示空安全

equals运算符==而不是.equals()

我应该使用哪个操作员?

第三个选项是添加到Java7和更高版本的Objects实用程序类中的static equals方法。

实例

下面是使用Month枚举的示例。

boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ;  // Returns `false`.

福利

我发现这种方法有几个好处:

零安全性两者均为空➙ 真的要么为空➙ 假的没有引发NullPointerException的风险紧凑、可读

它的工作原理

Objects.equals使用的逻辑是什么?

请自行查看OpenJDK的Java 10源代码:

return 
    ( a == b ) 
    || 
    ( 
        a != null 
        && 
        a.equals( b )
    )
;

只有一件事可以补充所有其他优秀的答案。当您使用简单的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));

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

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

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

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

Sonar规则之一是Enum值应与“==”进行比较。原因如下:

使用equals()测试枚举值的相等性是完全有效的,因为枚举是一个Object,每个Java开发人员都知道==不应用于比较Object的内容。同时,在enums上使用==:提供与equals()相同的预期比较(内容)比equals()更安全提供编译时(静态)检查而不是运行时检查出于这些原因,应该优先使用==而不是equals()。

最后但并非最不重要的是,enums上的==可以说比equals()更可读(更不冗长)。

我想补充多基因润滑剂的答案:

我个人更喜欢equals()。但它缺少类型兼容性检查。我认为这是一个重要的限制。

要在编译时进行类型兼容性检查,请在枚举中声明并使用自定义函数。

public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable

这样,您就获得了这两种解决方案的所有优点:NPE保护、易于阅读的代码和编译时的类型兼容性检查。

我还建议为enum添加一个未定义的值。