Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 352996

Summary: Optionally emit a warning if a class overrides hashCode() but not equals()
Product: [Eclipse Project] JDT Reporter: Gunter Ohrner <G.Ohrner>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: RESOLVED WONTFIX QA Contact:
Severity: enhancement    
Priority: P3 CC: amj87.iitr, daniel_megert, markus.kell.r, sebastian.zarnekow
Version: 3.7   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Gunter Ohrner CLA 2011-07-25 07:52:48 EDT
Build Identifier: 20110301-1815

The eclipse compiler supports a Warning if a class overrides equals(), but not hashCode().
In most cases, it will be equally wrong to implement hashCode(), but not equals(), yet Eclipse does not seem to offer a compiler setting to flag this constellation with a Warning.

Reproducible: Always
Comment 1 Ayushman Jain CLA 2011-07-25 08:09:43 EDT
I don't agree with this completely. When you override equals(), you've changed the implicit way two objects are compared (viz. via the memory addresses by default). This will ofcourse cause a change in the hashing function since two objects having similar memory addresses may now be different in your new implementation, and so it is always imperative to also override hashCode() when overriding equals(). Thats why we offer a warning.

Implementing hashCode() however has no impact on the way two objects are compared and equals() can still be left to its default implementation. Ofcourse in some cases, the user may have inadvertently left out overriding equals(), but then having a compiler warning for each of such cases where the user *might* have omitted something is not possible. We try to be a bit less aggresive when providing a new warning. :)

Let me know if i'm missing something here.
Comment 2 Sebastian Zarnekow CLA 2011-07-25 08:23:57 EDT
While I think that your point is interesting worth to discuss, it's based on the assumption that someone may actually want to override hashCode without overriding equals. We could try to analyze a reasonable sized codebase (e.g. eclipse.org) and collect the cases where hashcode was specialized but equals was left as is intentionally. I'd assume that there are only very few (if not zero) cases so a warning may be reasonable.
Comment 3 Gunter Ohrner CLA 2011-07-25 09:52:00 EDT
(In reply to comment #1)
> default). This will ofcourse cause a change in the hashing function since two
> objects having similar memory addresses may now be different in your new
> implementation, and so it is always imperative to also override hashCode() 

Two "different" (ie. "!equals()") objects having the same hashCode() is perfectly valid, though the other way around violates the contract.

I see that overriding Object's "equals()" almost certainly requires Object's "hashCode()" to be overridden as well, yet the opposite will be true if Object's "hashCode()" is overridden:
The only valid change would be an injective mapping of the original "hashCode()"'s value into another set of "hashCode()" values - any new implementation which behaves differently will be inconsistent with "equals()", if I'm not mistaken. I think there is limited use for this constellation.

In fact, every single case of an implemented "hashCode()" without an "equals()" I encountered so far turned out to be a bug.

However I could imagine that there might be cases where overriding "hashCode()" but not "equals()" might may sense if one is deriving from a class which already overrides both. Still I do avoid that in my code and would like to see a Warning if I accidentally make a mistake anyway. So maybe a new, additional compiler warning flag might be a sufficiently flexible solution?
Comment 4 Ayushman Jain CLA 2011-07-25 11:21:58 EDT
Dani/Markus, any thoughts? Any particular reason for the choice of having a warning for just one case and not vice versa?
Comment 5 Dani Megert CLA 2011-07-26 05:54:15 EDT
The warning is only in one direction because the Javadoc also only recommends that i.e. Object.equals(Object) says:

"Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes. "

but no such recommendation is given on Object.hashCode().
Comment 6 Gunter Ohrner CLA 2011-10-27 02:52:27 EDT
Mh, I still am not really convinced, but I guess that doesn't count too much.

However, hashCode()'s Javadoc states hashCode()'s contract as follows:
"If two objects are equal according to the <tt>equals(Object)</tt> method, then calling the <code>hashCode</code> method on each of the two objects must produce the same integer result."

I'm still wondering if there a legitimate reasons / use cases where you want to change hashCode() without changing equals() and without violating above guarantee...