问题
我知道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 热门回答(1251 赞)
两者在技术上都是正确的。如果你看看.equals()
的源代码,它只是简单地按照'=='。
我使用==
,但是,因为这将是无效的。
#2 热门回答(955 赞)
##可以在枚举上使用==吗?
是的:枚举具有严格的实例控件,允许您使用==
来比较实例。这是语言规范提供的保证(我强调):
JLS 8.9枚举枚举类型除了枚举常量定义的实例外没有其他实例。尝试显式实例化枚举类型是编译时错误。 Enum中的最后一个克隆方法确保枚举常量永远不会被克隆,并且序列化机制的特殊处理可确保重复实例从不会因反序列化而被创建。禁止枚举类型的反射实例化。总而言之,这四件事确保枚举类型的实例不会超出枚举常量定义的实例。因为每个枚举只有一个实例是常量,所以当比较两个对象引用时,如果知道至少其中一个引用了枚举常量,则允许使用==运算符代替equals方法。 (Enum中的equals方法是一个最终方法,仅在其参数上调用super.equals并返回结果,从而执行身份比较。)
这个保证足够强大,以至于Josh Bloch建议,如果你坚持使用单例模式,实现它的最好方法是使用单元enum
(参见Effective Java 2nd Edition,Item 3:强制单例财产与私人构造函数或枚举类型; alsoThread safety in Singleton)
==和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.equals(b)当且仅当a == b。如果类提供此保证,则其客户端可以使用==运算符而不是equals(Object)方法,这可以提高性能。枚举类型提供了这种保证。
总而言之,在enum
上使用==
的参数是:
- 有用。
- 速度更快。
- 在运行时更安全。
- 编译时更安全。
#3 热门回答(69 赞)
使用==
比较两个枚举值是可行的,因为每个枚举常量只有一个对象。
在附注中,如果你像这样编写equals()
,实际上不需要使用==
来编写空的安全代码:
public useEnums(SomeEnum a)
{
if(SomeEnum.SOME_ENUM_VALUE.equals(a))
{
...
}
...
}
这是一个最佳做法,称为Compare Constants From The Left,您绝对应该遵循。