我注意到以下代码段......
@Override
public boolean equals(Object otherObject) {
...
}
...不允许使用枚举,因为方法equals(Object x)
在Enum
中定义为final
。为什么会这样?
我想不出任何需要覆盖枚举equals(Object)
的用例。我只是想知道这种行为背后的原因。
答案 0 :(得分:37)
return this == other
以外的任何内容都会违反直觉并违反the principle of least astonishment。当且仅当它们是同一个对象并且覆盖此行为的能力容易出错时,预期两个枚举常量为equal
。
相同的推理适用于hashCode()
,clone()
,compareTo(Object)
,name()
,ordinal()
和getDeclaringClass()
。
虽然JLS没有激励选择让它成为最终,但在枚举here的背景下提及等于。片段:
Enum
中的equals方法是一个最终方法,仅在其参数上调用super.equals
并返回结果,从而执行身份比较。
答案 1 :(得分:3)
已经提供了一个强有力的直观概念,即enum
的实例(值)相等。允许重载equals
方法会导致违反概念,导致意外行为,错误等。
答案 2 :(得分:1)
有时我们需要处理不符合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;
}
答案 3 :(得分:0)
正是因为Java设计者无法想到任何可以想象的用于覆盖Enum.equals(Object)的用例,该方法被声明为final - 所以这样的覆盖是不可能的。
答案 4 :(得分:0)
我必须承认枚举是我想要覆盖equals()
的最后一件事。
我认为equals()
在枚举中是最终的原因是Java鼓励==
进行枚举比较,并且枚举中equals()
的实现只是使用它,因此允许{{1}被覆盖的是防止equals()
和==
表现不同,这是其他开发人员不会期望的。