Why Java does not allow overriding equals(Object) in an Enum?
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 invokessuper.equals
on its argument and returns the result, thus performing an identity comparison.
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.
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;}