40

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

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

...不允许用于枚举,因为该方法equals(Object x)定义finalEnum. 为什么会这样?

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

4

5 回答 5

46

任何事情return this == other都不会违反直觉并违反最小惊讶原则equal当且仅当它们是同一个对象并且覆盖此行为的能力容易出错时,两个枚举常量才被期望为。

同样的推理适用于hashCode(), clone(), compareTo(Object), name(), ordinal(), 和getDeclaringClass()


JLS 并没有促使选择使其成为最终的,但在此处的枚举上下文中提到了 equals 。片段:

in 中的 equals 方法Enum是最终方法,它仅调用super.equals其参数并返回结果,从而执行身份比较。

于 2010-06-03T09:47:33.773 回答
3

enum对于 an 的实例(值)相等意味着什么,已经提供了一个强烈的直观概念。允许重载equals方法将导致违反该概念,导致意外行为、错误等。

于 2010-06-03T09:42:28.277 回答
2

有时我们需要处理不符合 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;
}
于 2019-01-10T05:03:40.777 回答
1

正是因为 Java 设计者无法想到任何可想象的覆盖 Enum.equals(Object) 的用例,才将该方法声明为 final - 因此这种覆盖是不可能的。

于 2010-06-03T09:41:15.217 回答
0

我必须承认枚举是我想要覆盖的最后一件事equals()

我认为equals()枚举中的最终原因是Java鼓励==进行枚举比较,而枚举中的实现equals()只是使用它,因此允许equals()被覆盖是为了防止==equals()表现不同,这是其他开发人员不会想到的。

于 2010-06-03T09:49:55.780 回答