比较 Java 枚举成员: == or equals()?

2022-08-31 01:25:53

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

我应该使用哪个运算符?


答案 1

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

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


答案 2

可用于 ?==enum

是:枚举具有严格的实例控件,可用于比较实例。以下是语言规范提供的保证(由我强调):==

JLS 8.9 枚举

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

尝试显式实例化枚举类型是一个编译时错误。中的方法确保永远不会克隆常量,序列化机制的特殊处理可确保永远不会由于反序列化而创建重复的实例。禁止枚举类型的反射实例化。总之,这四件事确保了除了常量定义的实例之外,不存在任何类型的实例。final cloneEnumenumenumenum

由于每个常量只有一个实例,因此,如果已知其中至少有一个对象引用引用,则在比较两个对象引用时,允许使用 == 运算符代替 equals 方法。(in 中的方法只是调用其参数并返回结果,从而执行标识比较。enumequalsEnumfinalsuper.equals

Josh Bloch 建议,如果你坚持使用单例模式,实现它的最佳方法是使用单元素(参见:有效的 Java 2nd Edition,项目 3:使用私有构造函数或枚举类型强制实施单例属性;单例中的线程安全enum)


和 之间有什么区别?==equals

作为提醒,需要说的是,通常,不是可行的替代方案。但是,当它是(例如 with )时,需要考虑两个重要的区别:==equalsenum

==从不投掷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.equals(b)a==b==equals(Object)

总而言之,使用 on 的参数是:==enum

  • 它的工作原理。
  • 它更快。
  • 它在运行时更安全。
  • 它在编译时更安全。