我知道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()在大多数情况下都有效。 您没有比较其他人指出的完全不同类型的对象的编译时间确定性是有效和有益的,但是比较两种不同编译时间类型的对象的特殊类型的错误也可以通过FindBugs找到(并且可能通过Eclipse / IntelliJ编译时间检查),因此Java编译器发现它并没有增加太多额外的安全性。
然而:
这样的事实==不会抛出NPE在我心目中是一个缺点 == 。 几乎不需要enum类型为null ,因为您可能希望通过null表示的任何额外状态都可以作为附加实例添加到enum中。 如果它意外地为null ,那么我宁愿拥有一个NPE而不是==默默地评估为false。 因此,我不同意它在运行时的观点是更安全的 。 最好养成永远不要让enum值为
== 更快的说法也是假的。 在大多数情况下,您将在编译时类型为enum类的变量上调用.equals() ,在这些情况下,编译器可以知道这与==相同(因为enum的equals()方法可以(不会被覆盖)并可以优化函数调用。 我不确定编译器当前是否这样做,但是如果没有这样做,结果证明这是Java整体的性能问题,那么我宁愿修复该编译器,也不愿让100,000个Java程序员更改其编程样式以适应特定编译器版本的性能特征。
enums是对象。 对于所有其他对象类型,标准比较是.equals() ,而不是== 。 我认为对enums进行例外处理是危险的,因为您可能最终会意外地将Object与==而不是equals()进行比较,尤其是当您将enum重构为非枚举类时。 在这种重构的情况下,从上面的工作原理是错误的。 为了使自己确信==的使用是正确的,您需要检查所讨论的值是enum还是基元。 如果它是一个非enum类,那将是错误的,但是很容易遗漏,因为代码仍然可以编译。 使用.equals()错误的唯一情况是所讨论的值是否是基元; 在这种情况下,代码将无法编译,因此更容易遗漏。 因此, .equals()更容易被识别为正确的,并且对于将来的重构更安全。
我实际上认为Java语言应该在Objects上定义==,以在左侧值上调用.equals(),并为对象标识引入一个单独的运算符,但这不是Java的定义方式。
总之,我仍然认为参数支持对enum类型使用.equals() 。
#2楼
如果枚举是正确的,那么正确!
#3楼
两者在技术上都是正确的。 如果您查看.equals()的源代码,则它仅.equals() == 。
我使用== ,但是这将是null安全的。
#4楼
使用==比较两个枚举值是可行的,因为每个枚举常量只有一个对象。
附带说明一下,如果您像这样编写equals() ,则实际上无需使用==来编写空安全代码:
public useEnums(final SomeEnum a) {
if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
…
}
…
}
这是被称为“ 从左边比较常量”的最佳实践,您绝对应该遵循。
#5楼
我想补充多基因润滑剂的答案:
我个人更喜欢equals()。 但是它对类型兼容性进行检查。 我认为这是一个重要的限制。
要在编译时检查类型兼容性,请在枚举中声明并使用自定义函数。
public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable
这样,您将获得两种解决方案的全部优势:NPE保护,易于阅读的代码以及在编译时进行类型兼容性检查。
我还建议为枚举添加一个UNDEFINED值。