我知道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)
{
...
}
...
}
我应该使用哪个操作员?
正如其他人所说,==和.equals()在大多数情况下都有效。编译时确定您没有比较其他人指出的完全不同类型的对象是有效和有益的,但是FindBugs(可能还有Eclipse/InIntelliJ编译时检查)也会发现比较两种不同编译时类型的对象的特定类型的错误,因此Java编译器发现它不会增加太多额外的安全性。
然而:
==从未在我的脑海中抛出NPE这一事实是==的缺点。几乎不需要枚举类型为null,因为您可能希望通过null表达的任何额外状态都可以作为附加实例添加到枚举中。如果它意外为空,我宁愿使用NPE而不是==默默地计算为false。所以,我不同意运行时更安全的观点;最好养成一个习惯,永远不要让枚举值为@Nullable。==更快的论点也是假的。在大多数情况下,您将对编译时类型为enum类的变量调用.equals(),在这些情况下,编译器可以知道这与==相同(因为enum的equals()方法不能被重写),并可以优化函数调用。我不确定编译器当前是否做到了这一点,但如果没有做到,并且最终证明是Java整体性能问题,那么我宁愿修复编译器,也不愿让100000名Java程序员更改其编程风格以适应特定编译器版本的性能特征。enums是对象。对于所有其他Object类型,标准比较是.equals(),而不是==。我认为为枚举设置异常是危险的,因为您可能会意外地将Object与==而不是equals()进行比较,尤其是在将枚举重构为非枚举类时。在这种重构的情况下,上面的It work点是错误的。为了让自己相信使用==是正确的,您需要检查所讨论的值是枚举还是基元;如果它是一个非枚举类,那么它是错误的,但很容易错过,因为代码仍然可以编译。唯一错误使用.equals()的情况是,所讨论的值是基元;在这种情况下,代码不会编译,因此很难错过。因此,.equals()更容易识别为正确的,并且更安全地防止将来的重构。
实际上,我认为Java语言应该在左边的值上定义==on Objects to call.equals(),并为对象标识引入一个单独的运算符,但Java并不是这样定义的。
总之,我仍然认为参数支持对枚举类型使用.equals()。
下面是一个粗略的时间测试,以比较两者:
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
第一个(equals)执行虚拟调用并测试堆栈中的返回布尔值。第二个(==)比较直接来自堆栈的对象地址。在第一种情况下,有更多的活动。
我对两个国际单项体育联合会一次进行了几次测试。“==”速度稍快。