我注意到以下代码段...
@Override
public boolean equals(Object otherObject) {
...
}
...不允许用于枚举,因为该方法equals(Object x)
定义final
为Enum
. 为什么会这样?
我想不出任何需要覆盖equals(Object)
Enum 的用例。我只是想知道这种行为背后的原因。
我注意到以下代码段...
@Override
public boolean equals(Object otherObject) {
...
}
...不允许用于枚举,因为该方法equals(Object x)
定义final
为Enum
. 为什么会这样?
我想不出任何需要覆盖equals(Object)
Enum 的用例。我只是想知道这种行为背后的原因。
任何事情return this == other
都不会违反直觉并违反最小惊讶原则。equal
当且仅当它们是同一个对象并且覆盖此行为的能力容易出错时,两个枚举常量才被期望为。
同样的推理适用于hashCode()
, clone()
, compareTo(Object)
, name()
, ordinal()
, 和getDeclaringClass()
。
JLS 并没有促使选择使其成为最终的,但在此处的枚举上下文中提到了 equals 。片段:
in 中的 equals 方法
Enum
是最终方法,它仅调用super.equals
其参数并返回结果,从而执行身份比较。
enum
对于 an 的实例(值)相等意味着什么,已经提供了一个强烈的直观概念。允许重载equals
方法将导致违反该概念,导致意外行为、错误等。
有时我们需要处理不符合 Java 命名标准的数据。能够做这样的事情会很好:
public enum Channel
{
CallCenter("Call Center"),
BankInternal("Bank Internal"),
Branch("Branch");
private final String value;
Channel(String value)
{
this.value = value;
}
@Override
public String toString()
{
return value;
}
public static Channel valueOf(String value)
{
for (Channel c : Channel.values())
if (c.value.equals(value))
return c;
return null;
}
@Override
public boolean equals(Object other)
{
if (other instanceof String)
other = Channel.valueOf((String)other);
return super.equals(other);
}
}
需要修改“String”类以适应...
public boolean equals (Object object) {
if (object == this) return true;
if (object instanceof Enum)
object = object.toString();
if (object instanceof String) {
String s = (String)object;
// There was a time hole between first read of s.hashCode and second read
// if another thread does hashcode computing for incoming string object
if (count != s.count ||
(hashCode != 0 && s.hashCode != 0 && hashCode != s.hashCode))
return false;
return regionMatches(0, s, 0, count);
}
return false;
}
正是因为 Java 设计者无法想到任何可想象的覆盖 Enum.equals(Object) 的用例,才将该方法声明为 final - 因此这种覆盖是不可能的。
我必须承认枚举是我想要覆盖的最后一件事equals()
。
我认为equals()
枚举中的最终原因是Java鼓励==
进行枚举比较,而枚举中的实现equals()
只是使用它,因此允许equals()
被覆盖是为了防止==
和equals()
表现不同,这是其他开发人员不会想到的。