比较Java中的枚举成员:使用==还是equals()?

31 浏览
0 Comments

比较Java中的枚举成员:使用==还是equals()?

我知道Java枚举被编译成具有私有构造函数和许多公共静态成员变量的类。在比较给定枚举的两个成员时,我通常使用.equals(),例如:

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

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

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

我应该使用哪个运算符?

admin 更改状态以发布 2023年5月22日
0
0 Comments

枚举类型可以使用 == 吗?

可以:枚举类型具有严格的实例控制,允许您使用 == 比较实例。以下是语言规范提供的保证(我强调的部分):

JLS 8.9 枚举类型

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

在尝试显式实例化枚举类型时,会产生编译时错误。在 Enum 中的 final clone 方法确保 enum 常量永远无法被克隆,并且序列化机制的特殊处理确保不会因反序列化而创建重复实例。禁止反射实例化枚举类型。这四件事情共同确保不存在除由枚举常量定义的实例之外的任何 enum 实例。

由于每个 enum 常量只有一个实例,如果已知其中至少一个引用了一个 enum 常量,可以在比较两个对象引用时使用 == 运算符替代 equals 方法。Enum 中的 equals 方法是一个 final 方法,它只在其参数上调用 super.equals 并返回结果,从而执行身份比较。)

这种保证足够强大,以至于Josh Bloch建议,如果您坚持使用单例模式,则最好的实现方式是使用一个单元素的 enum(请参见:Effective Java 2nd Edition,第3项:使用私有构造函数或枚举类型强制执行单例属性;还可以查看 单例模式中的线程安全

“==”和“equals”有什么区别?

需要提醒的是,通常来讲,“==”不是“equals”的替代品。然而,在某些情况下,例如使用enum时,“==”可以作为可行的替代方法。但是,需要考虑两个重要的差别:

“==”永远不会抛出NullPointerException

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!


适用情况下是否应该使用“==”?

Bloch特别提到,具有正确的实例控制的不可变类可以向其客户端保证“==”是可用的。enum被特别提到作为示例。

条款1:考虑使用静态工厂方法代替构造器

……它使得一个不可变的类可以保证不存在两个相等的实例:当且仅当a==b时才会有a.equals(b)。如果一个类做出了这样的保证,那么它的客户端可以使用“==”运算符而不是“equals(Object)”方法,这可能会提高性能。枚举类型提供这种保证。

总的来说,使用“==”来处理enum的论点如下:

  • 有效。
  • 速度更快。
  • 在运行时更安全。
  • 在编译时更安全。
0
0 Comments

两种方式在技术上都是正确的。如果你查看.equals()的源代码,它只是依赖于==

我使用==,因为它是安全的,可以避免空指针异常。

0