簡體   English   中英

為什么 Java 不允許在枚舉中覆蓋 equals(Object)?

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

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

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

...不允許用於 Enum,因為方法equals(Object x)Enum中定義為final 為什么會這樣?

我想不出任何需要為 Enum 覆蓋equals(Object)的用例。 我只是想知道這種行為背后的原因。

任何東西,但return this == other將是反直覺的,並違反最不驚訝的原則 當且僅當它們是同一個對象並且覆蓋此行為的能力容易出錯時,預期兩個枚舉常量是equal

相同的推理適用於hashCode()clone()compareTo(Object)name()ordinal()getDeclaringClass()


JLS並沒有激勵選擇讓它成為最終版本,但在這里的枚舉語中提到了相同的內容。 片段:

Enum的equals方法是一個最終方法, super.equals在其參數上調用super.equals並返回結果,從而執行身份比較。

已經提供了一個強有力的直觀概念,即對enum實例(值)的意義是什么。 允許重載equals方法會導致違反概念,導致意外行為,錯誤等。

正是因為Java設計者無法想到任何可以想象的用於覆蓋Enum.equals(Object)的用例,該方法被聲明為final - 所以這樣的覆蓋是不可能的。

有時我們需要處理不符合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;
}

我必須承認枚舉是我想要覆蓋equals()的最后一件事。

我認為equals()在枚舉中是最終的原因是Java鼓勵==進行枚舉比較,並且枚舉中equals()的實現只是使用它,因此允許重寫equals()是為了防止==equals()從不同的表現,這點是其他開發商也不會想到。

我是大多數人的意見。 如果禁止 Enum::equals 的覆蓋,我不認為這是遵循最小驚訝原則。 我認為是不要破壞 Java。

在 JVM 和一些舊類(如 EnumMap)中,Enum 標識可能在內部使用 int 進行編碼。 例如,如果我們允許覆蓋 Enum::equals,那么 EnumMap<K, V> 將違反 Map 的約定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM