比较Java枚举成员:==或等于()?
我知道Java枚举被编译成带有私有构造函数和一堆公共静态成员的类。在比较给定枚举的两个成员时,我总是使用比较Java枚举成员:==或等于()?,java,enums,Java,Enums,我知道Java枚举被编译成带有私有构造函数和一堆公共静态成员的类。在比较给定枚举的两个成员时,我总是使用.equals(),例如 public useEnums(SomeEnum a) { if(a.equals(SomeEnum.SOME_ENUM_VALUE)) { ... } ... } 但是,我刚刚遇到一些使用equals运算符而不是.equals()的代码: 我应该使用哪个运算符?对于枚举,两者都是正确的 对于枚举,两者都是正确的 两者
.equals()
,例如
public useEnums(SomeEnum a)
{
if(a.equals(SomeEnum.SOME_ENUM_VALUE))
{
...
}
...
}
但是,我刚刚遇到一些使用equals运算符而不是.equals()的代码:
我应该使用哪个运算符?对于枚举,两者都是正确的 对于枚举,两者都是正确的 两者在技术上都是正确的。如果您查看
.equals()
的源代码,它只是遵从=
但是,我使用
==
,因为这将是空安全的。两者在技术上都是正确的。如果您查看.equals()
的源代码,它只是遵从=
但是,我使用
=
,因为这将是空安全的。使用=
比较两个枚举值是有效的,因为每个枚举常量只有一个对象
另一方面,如果您这样编写equals()
,实际上不需要使用==
来编写空安全代码:
public useEnums(final SomeEnum a) {
if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
…
}
…
}
这是一个众所周知的最佳实践,您绝对应该遵循。使用
=
比较两个枚举值是有效的,因为每个枚举常量只有一个对象
另一方面,如果您这样编写equals()
,实际上不需要使用==
来编写空安全代码:
public useEnums(final SomeEnum a) {
if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
…
}
…
}
这是一个众所周知的最佳实践,您绝对应该遵循。是否可以在enum
上使用=
?
是:枚举具有紧密的实例控件,允许您使用==
来比较实例。以下是语言规范提供的保证(我强调):
枚举类型除了由其枚举常量定义的实例外,没有其他实例
尝试显式实例化枚举类型是编译时错误。Enum
中的final clone
方法确保永远不能克隆Enum
常量,序列化机制的特殊处理确保永远不会由于反序列化而创建重复实例。禁止枚举类型的反射实例化。这四个因素共同确保enum
类型的实例不存在于enum
常量定义的实例之外
由于每个枚举
常量只有一个实例,在比较两个对象引用时,如果已知其中至少有一个引用了枚举
常量,则允许使用=
操作符代替等于
方法。(Enum
中的equals
方法是一个final
方法,它仅对其参数调用super.equals
,并返回结果,从而执行身份比较。)
Josh Bloch建议,如果您坚持使用singleton模式,实现它的最佳方法是使用单个元素enum
(请参阅:Efficive Java第二版,第3项:使用私有构造函数或enum类型强制singleton属性;另外)
=
和等于
之间有什么区别?
需要提醒的是,一般来说,==
不是等于
的可行替代方案。但是,如果是(例如使用enum
),则需要考虑两个重要的区别:
=
从不抛出NullPointerException
=
在编译时接受类型兼容性检查
如果适用,是否应使用
==
?
Bloch特别提到,对其实例进行适当控制的不可变类可以向其客户机保证=
是可用的<代码>枚举是特别提到的示例
项目1:考虑静态工厂方法,而不考虑构造函数< /P> […]它允许不可变类保证不存在两个相等的实例:
a.equals(b)
当且仅当a==b
时。如果一个类保证了这一点,那么它的客户端可以使用=
操作符而不是equals(Object)
方法,这可能会提高性能。枚举类型提供了这种保证
总之,在enum
上使用=
的参数如下:
- 它起作用了
- 它更快
- 它在运行时更安全
- 它在编译时更安全
枚举上使用==
?
是:枚举具有紧密的实例控件,允许您使用==
来比较实例。以下是语言规范提供的保证(我强调):
枚举类型除了由其枚举常量定义的实例外,没有其他实例
尝试显式实例化枚举类型是编译时错误。Enum
中的final clone
方法确保永远不能克隆Enum
常量,序列化机制的特殊处理确保永远不会由于反序列化而创建重复实例。禁止枚举类型的反射实例化。这四个因素共同确保enum
类型的实例不存在于enum
常量定义的实例之外
由于每个枚举
常量只有一个实例,在比较两个对象引用时,如果已知其中至少有一个引用了枚举
常量,则允许使用=
操作符代替等于
方法。(Enum
中的equals
方法是一个final
方法,它仅在参数和参数上调用super.equals
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!
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());
}
}
21 getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
24 getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
27 invokevirtual EnumCompareSpeedTest$TestEnum.equals(java.lang.Object) : boolean [28]
30 ifeq 36
36 getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
39 getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
42 if_acmpne 48
public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable
package first.pckg
public enum Category {
JAZZ,
ROCK,
POP,
POP_ROCK
}
package second.pckg
public enum Category {
JAZZ,
ROCK,
POP,
POP_ROCK
}
import second.pckg.Category;
...
Category.JAZZ.equals(item.getCategory())
import second.pckg.Category;
...
Category.JAZZ == item.getCategory()
Objects.equals( thisEnum , thatEnum )
boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ; // Returns `false`.
return
( a == b )
||
(
a != null
&&
a.equals( b )
)
;