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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2964704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:43:47  来源:igfitidea点击:

Why Java does not allow overriding equals(Object) in an Enum?

javaenumsapi-design

提问by Ashwin Prabhu

I've noticed that the following snippet...

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

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

...is not allowed for an Enum, since the method equals(Object x)is defined as finalin Enum. Why is this so?

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

I cannot think of any use case which would require overriding equals(Object)for Enum. I'm just curious to know the reasoning behind this behavior.

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

回答by aioobe

Anything but return this == otherwould be counter intuitive and violate the principle of least astonishment. Two enum constants are expected to be equalif and only if they are the same object and the ability to override this behavior would be error prone.

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

Same reasoning applies to hashCode(), clone(), compareTo(Object), name(), ordinal(), and getDeclaringClass().

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



The JLS does not motivate the choice of making it final, but mentions equals in the context of enums here. Snippet:

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

The equals method in Enumis a final method that merely invokes super.equalson its argument and returns the result, thus performing an identity comparison.

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

回答by Stephen C

There is already provides a strong intuitive notion of what it means for instances (values) of an enumto be equal. Allowing the overloading the equalsmethod would lead to that notion being violated, leading to unexpected behavior, bugs and so on.

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

回答by D. Matthew Johnson

Sometimes we need to deal with data that does not conform to Java naming standards. It would be nice to be able to do something like this:

有时我们需要处理不符合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);
    }
}

The "String" class would need to be modified to accommodate...

需要修改“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;
}

回答by Jean Hominal

It is precisely because the Java designers could not think of any conceivable use case for overriding Enum.equals(Object) that that method is declared as final - so that such overriding would be impossible.

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

回答by Oak

I must confess enums are the last thing I would want to override equals()in.

我必须承认枚举是我最不想覆盖的东西equals()

I think the reason equals()is final in enums is that Java encourages ==for enum comparison, and the implementation of equals()in enums simply uses it, So allowing equals()from being overridden is to prevent ==and equals()from behaving differently, which is something other developers would not expect.

我认为equals()enums的原因是 final 是 Java 鼓励==进行 enum 比较,而equals()in enums的实现只是使用它,所以允许equals()被覆盖是为了防止==equals()行为不同,这是其他开发人员不会想到的。