NetBeans awkward warning overriding hashCode

B

Ben Phillips

This seems to be a minor irritation with NetBeans: if you have a class A
that overrides equals() with something like

if (o == this) return true;
if (o == null) return false;
if (!o instanceof A) return false;
// and maybe
if (o.getClass() != getClass()) return false; // objects of different
// subclasses aren't equal
return equalTo((A)o);

public abstract boolean equalTo (A other);

and hashCode with something like

throw new Error("My subclass should have overridden me!");

and then, in a subclass B, implement equalTo and hashCode (to be
consistent with one another), NetBeans warns of having overridden
hashCode without equals.

This is just a touch annoying, since it means you either have the
warning or else have to repeat a bunch of boilerplate equals() code in
every subclass.

Is there an @SuppressWarnings for this, or a NetBeans update in the
works that will make it smarter about guessing if a subclass really is
implementing equalTo in some indirect manner (say, because it implements
a boolean-returning abstract method the superclass declares and only
calls from inside equals())?
 
D

Daniel Pitts

Ben said:
This seems to be a minor irritation with NetBeans: if you have a class A
that overrides equals() with something like

if (o == this) return true;
if (o == null) return false;
if (!o instanceof A) return false;
// and maybe
if (o.getClass() != getClass()) return false; // objects of different
// subclasses aren't equal
return equalTo((A)o);

public abstract boolean equalTo (A other);

and hashCode with something like

throw new Error("My subclass should have overridden me!");

and then, in a subclass B, implement equalTo and hashCode (to be
consistent with one another), NetBeans warns of having overridden
hashCode without equals.

This is just a touch annoying, since it means you either have the
warning or else have to repeat a bunch of boilerplate equals() code in
every subclass.

Is there an @SuppressWarnings for this, or a NetBeans update in the
works that will make it smarter about guessing if a subclass really is
implementing equalTo in some indirect manner (say, because it implements
a boolean-returning abstract method the superclass declares and only
calls from inside equals())?

public final boolean equals(Object o) { /*...code from above...*/ }
public final int hashCode() { return realHashCode(); }

protected abstract boolean equalTo(A other);
protected abstract int realHashCode();

This will do two things:
force people to implement both realHashCode and equalTo,
and it will prevent people from overriding your equals and hashCode in
ways that circumvent what you've tried to do.

HTH.
Daniel.
 
S

softwarepearls_com

This seems to be a minor irritation with NetBeans: if you have a class A
that overrides equals() with something like

if (o == this) return true;
if (o == null) return false;
if (!o instanceof A) return false;
// and maybe
if (o.getClass() != getClass()) return false;    // objects of different
                                               // subclasses aren't equal
return equalTo((A)o);

public abstract boolean equalTo (A other);

and hashCode with something like

throw new Error("My subclass should have overridden me!");

and then, in a subclass B, implement equalTo and hashCode (to be
consistent with one another), NetBeans warns of having overridden
hashCode without equals.

This is just a touch annoying, since it means you either have the
warning or else have to repeat a bunch of boilerplate equals() code in
every subclass.

Is there an @SuppressWarnings for this, or a NetBeans update in the
works that will make it smarter about guessing if a subclass really is
implementing equalTo in some indirect manner (say, because it implements
a boolean-returning abstract method the superclass declares and only
calls from inside equals())?

I'm developing a stand alone Java tool which, among other things, can
analyse classes for flawed hashCode/equals interaction.. whatever the
override or delegation contortions the implementation imposes.

If you're interested in such a tool, I'd very much appreciate
receiving feedback by way of a questionnaire I've prepared:
www.softwarepearls.com/market_research.html

As a thank you, anyone filling in the form will get free early access
to the tool (it's commercial).
 
D

Damon Getsman

This seems to be a minor irritation with NetBeans: if you have a class A
that overrides equals() with something like

if (o == this) return true;
if (o == null) return false;
if (!o instanceof A) return false;
// and maybe
if (o.getClass() != getClass()) return false;    // objects of different
                                               // subclasses aren't equal
return equalTo((A)o);

public abstract boolean equalTo (A other);

and hashCode with something like

throw new Error("My subclass should have overridden me!");

and then, in a subclass B, implement equalTo and hashCode (to be
consistent with one another), NetBeans warns of having overridden
hashCode without equals.
Unfortunately I don't knon the answer to your question, but I did want
to throw in my $.02 here. NetBeans is a TERRIBLY buggy piece of
software and [relatively] often has crashes that will lead to losses
of data. You don't even need to be doing anything complex in the app,
it can happen when you're just navigating in the code editor or typing
in code.

I mentioned this on the Sun forums website and submitted a bug
report. The Sun forums website gave me the great advice to start
saving every 30 seconds and quit whining because it was my fault for
not doing that in the first place. I've had no answer on the bug
report. So then I started googling and found a whole host of issues
that have never been resolved with NetBeans, despite being around for
5 years or more.

I'd switch to an IDE like Eclipse that has a decent development team
behind it...
 
J

Joshua Cranmer

Ben said:
and then, in a subclass B, implement equalTo and hashCode (to be
consistent with one another), NetBeans warns of having overridden
hashCode without equals.

And why shouldn't it? There is no easy way to determine that equals has
"in effect" been overridden when you rely on auxiliary methods. I'm
reasonably confident I could come up with something that breaks any
detection method that is generated without resorting to reflection (and
once you get to reflection, all bets are off).

If you want to use auxiliary methods, force people to do the right thing
by forcing them to override both equals and hashCode via auxiliaries, as
Daniel pointed out.
 
B

Ben Phillips

Joshua said:
And why shouldn't it? There is no easy way to determine that equals has
"in effect" been overridden when you rely on auxiliary methods.

But it can, in principle, guess, based on if a method called by the
superclass equals has been overridden. It may, of course, guess wrong.
It can't be expected to detect every potential error, though; it
wouldn't warn if you override equals and hashCode but didn't make them
consistent (so, hashCode could return different values for distinct but
"equal" objects), for example.

With warnings, there's a balance to be struck between being too niggledy
and letting probable errors escape unnoticed. As a rule, something
"suspicious" should be flagged, but also should be overridable.

In this case, it turns out that using a "dummy"
punt-to-subclass-implementation of hashCode, even where the superclass
gives it no behavior of its own, does the trick (and the performance
penalty probably goes away once the JIT has hit that part of the code).

If the abstract superclass has some hash-influencing state of its own,
this becomes more "natural":

public boolean equals (Object o) {
if (o == this) return true;
if (o == null) return false;
if (!o instanceOf MyClass) return false;
MyClass foo = (MyClass)o;
if (!foo.member.equals(member)) return false;
return subclassEquals(foo);
}

public int hashCode () {
return member.hashCode()*17 + subclassHashCode();
}
 
R

Roger Lindsjö

Ben said:
If the abstract superclass has some hash-influencing state of its own,
this becomes more "natural":

public boolean equals (Object o) {
if (o == this) return true;
if (o == null) return false;
if (!o instanceOf MyClass) return false;
MyClass foo = (MyClass)o;
if (!foo.member.equals(member)) return false;
return subclassEquals(foo);
}

public int hashCode () {
return member.hashCode()*17 + subclassHashCode();
}

The check "if (o == null)" can be skipped as instanceof for a null
object always returns false.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top