为什么 Java 不允许在 Enum 中重写 equals(Object) ?

发布于 2024-09-04 05:13:50 字数 432 浏览 2 评论 0 原文

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

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

...不允许用于枚举,因为方法 equals(Object x)final href="http://download.oracle.com/javase/6/docs/api/java/lang/Enum.html#equals%28java.lang.Object%29" rel="noreferrer">Enum< /代码>。为什么会这样呢?

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

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 final in Enum. Why is this so?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

薄暮涼年 2024-09-11 05:13:50

除了 return this == other 之外的任何内容都将违反直觉,并且违反最小惊讶原则。当且仅当两个枚举常量是同一个对象时,它们才应相等,并且覆盖此行为的能力很容易出错。

同样的推理也适用于 hashCode()clone()compareTo(Object)name()、<代码>ordinal()和getDeclaringClass()


JLS 并不促使选择将其定为最终版本,而是在枚举上下文中提到 equals 此处。片段:

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


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

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


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

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

潦草背影 2024-09-11 05:13:50

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

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

旧街凉风 2024-09-11 05:13:50

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

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:

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...

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;
}
满地尘埃落定 2024-09-11 05:13:50

我会采纳大多数人的意见。如果禁止覆盖 Enum::equals,我认为这并不是遵循最小惊讶原则。我认为是为了不破坏Java。

在 JVM 和一些旧的类(例如 EnumMap)中,Enum 标识可以在内部使用 int 进行编码。例如,如果我们允许重写 Enum::equals,则 EnumMap会破坏Map的契约。

I am going the majority opinion. If the override of Enum::equals is forbidden, I don't think it was to follow the principle of least astonishment. I think it is to not break Java.

In the JVM, and in some old classes such like EnumMap, Enum identities may be coded internally with an int. For example, if we allow to override Enum::equals, then EnumMap<K, V> would break the contract of Map.

暮年 2024-09-11 05:13:50

正是因为 Java 设计者无法想到任何可想象的重写 Enum.equals(Object) 的用例,所以该方法被声明为 Final - 因此这种重写是不可能的。

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.

平安喜乐 2024-09-11 05:13:50

我必须承认枚举是我最不想重写的 equals() 。

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文