为什么Java不允许在枚举中覆盖equals(Object)?

时间:2010-06-03 09:36:22

标签: java enums api-design

我注意到以下代码段......

@Override
public boolean equals(Object otherObject) {
    ...
}

...不允许使用枚举,因为方法equals(Object x)Enum中定义为final。为什么会这样?

我想不出任何需要覆盖枚举equals(Object)的用例。我只是想知道这种行为背后的原因。

5 个答案:

答案 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()==表现不同,这是其他开发人员不会期望的。