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

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

技术背景

在Java编程中,经常需要对枚举类型的成员进行比较。对于枚举成员的比较,有两种常见的方式:使用 == 运算符和使用 equals() 方法。了解这两种方式的区别和适用场景,对于编写高效、安全的Java代码至关重要。

实现步骤

1. 理解枚举类型的特性

Java的枚举类型具有严格的实例控制,即每个枚举常量只有一个实例。这是由Java语言规范保证的,具体如下:

  • 枚举类型除了由其枚举常量定义的实例外,没有其他实例。
  • 试图显式实例化枚举类型是编译时错误。
  • Enum 类中的 final clone 方法确保枚举常量永远不会被克隆。
  • 序列化机制的特殊处理确保反序列化不会创建重复的实例。
  • 反射实例化枚举类型是被禁止的。

2. 比较 ==equals() 的使用

使用 == 比较

1
2
3
enum Color { BLACK, WHITE };
Color nothing = null;
if (nothing == Color.BLACK); // 运行正常

== 比较的是对象的引用,对于枚举类型,由于每个常量只有一个实例,因此可以使用 == 进行比较。同时,== 不会抛出 NullPointerException,并且在编译时会进行类型兼容性检查。

使用 equals() 比较

1
2
3
enum Color { BLACK, WHITE };
Color nothing = null;
if (nothing.equals(Color.BLACK)); // 抛出NullPointerException

equals() 方法在 Enum 类中是一个 final 方法,它实际上调用了 super.equals,进行的是引用比较。但当比较的对象为 null 时,会抛出 NullPointerException

3. 考虑使用 Objects.equals() 方法

1
2
3
4
import java.util.Objects;
import java.time.Month;

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

Objects.equals() 方法是Java 7及以后版本提供的实用方法,它具有空安全性,不会抛出 NullPointerException,并且代码简洁易读。

核心代码

比较 ==equals() 的性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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());
}
}

通过上述代码可以比较 ==equals() 的性能,实际测试中 == 会稍微快一些。

使用自定义方法进行枚举比较

1
2
3
4
5
6
7
8
9
10
11
enum MyEnum {
VALUE1, VALUE2;

public boolean isEquals(MyEnum enumVariable) {
return this == enumVariable;
}

public static boolean areEqual(MyEnum enumVariable1, MyEnum enumVariable2) {
return enumVariable1 == enumVariable2;
}
}

通过自定义方法,可以在保证空安全和易读性的同时,实现编译时的类型兼容性检查。

最佳实践

  • 使用 ==:当确定枚举值不会为 null,并且需要更高的性能和编译时的类型检查时,推荐使用 ==
  • 使用 equals():如果代码需要考虑枚举值可能为 null 的情况,或者为了提高代码的通用性和可维护性,建议使用 equals()
  • 使用 Objects.equals():当需要确保代码的空安全性,并且追求代码的简洁性时,可以使用 Objects.equals() 方法。

常见问题

1. 使用 == 比较不同包下相同定义的枚举

如果使用 equals() 比较不同包下相同定义的枚举,可能会得到意外的结果。而使用 == 会在编译时报错,提示类型不兼容。

2. 枚举类型重构为其他类型

如果将枚举类型重构为普通类实例,使用 == 进行比较的代码可能会出现问题,而使用 equals() 则更容易发现问题。

3. 历史版本的JDK问题

在Sun JDK 6u10及更早版本中,存在一个影响反序列化枚举使用 == 比较的bug,但这属于比较特殊的情况。


Java枚举成员比较:使用==还是equals()?
https://119291.xyz/posts/java-enum-comparison-using-equal-or-equals/
作者
ww
发布于
2025年5月19日
许可协议