Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!.POSTED!not-for-mail From: Novice Newsgroups: comp.lang.java.programmer Subject: Re: Additional logging questions Date: Tue, 28 Feb 2012 01:48:36 +0000 (UTC) Organization: Your Company Lines: 109 Message-ID: References: <4f4ae583$0$281$14726298@news.sunsite.dk> NNTP-Posting-Host: Dmxgbnvd+eoRDUV2lwYf7Q.user.speranza.aioe.org X-Complaints-To: abuse@aioe.org User-Agent: Xnews/5.04.25 X-Antivirus-Status: Clean X-Notice: Filtered by postfilter v. 0.8.2 X-Antivirus: avast! (VPS 120227-0, 2012-02-27), Outbound message Xref: x330-a1.tempe.blueboxinc.net comp.lang.java.programmer:12464 Lew wrote in news:jigr8v$jhh$1@news.albasani.net: > Novice wrote: >> Lew wrote: >>> 'toString()' should always give a useful way to identify the >>> specific instance. >>> >> That's why I was displaying the name of the table so I'm going to >> take that as a "yes" ;-) >> >>> It should depend on (and usually only on) the same fields used to >>> drive 'hashCode()' and 'equals()' and if supported, 'compareTo()' >>> (which should always be consistent with each other). >>> >> I don't touch hashCode(), equals() or compareTo() very often at all. >> Or toString() either for that matter. But overriding hashCode() and >> equals() solved a big problem for me recently. I was writing a holder >> class that contained three fields, a table name, a row number and a >> column number, as a key for a hash map and then storing the column >> width in the value portion of the map. But when I tried to look up a >> given combination of table name, row number and column number I was >> never finding values that I knew were there. I googled and found out >> that I needed to revise hashCode() and equals() and rougly what those >> changes needed to be and then my lookups went fine. But I didn't >> touch compareTo(). Hmm, maybe I need to revisit that and make sure it >> doesn't need some tweaking too.... > > The default 'Object#equals()' method gives (almost) the same answer as > the == operator - two instances are equal iff (if and only if) they > are the same instance. That's called "object equality" or "instance > equality". > > Often we want value equality. It's not very helpful, for example, for > > new Integer(67551) != new Integer(67551) > > to be true. > > That means equality of different instances, provided their values > match in some defined way. > > For 'Integer', value equality depends on only one attribute, the > underlying 'int' field. > > For a more complicated type, there might be more than one attribute. > For example, you might regard two widgets as equal iff they have the > same owner and color: > > public class Widget > { > private final Owner owner; // assume getter methods for brevity > private final Color color; > public Widget(Owner owner, Color color) > { > if (owner == null || color == null) > { > throw new IllegalArgumentException("null"); > } > this.owner = owner; > this.color = color' > assert this.owner != null && this.color != null; > } > @Override public boolean equals(Object other) > { > if (other == this) { return true; } > if (! (other instanceof Widget)) { return false; } > Widget widget = (Widget) other; > return this.getOwner().equals(widget.getOwner()) > && this.getColor().equals(widget.getColor() > } > } > > But wait! 'hashCode()', which is a shortcut for 'equals()' (well, > really for "not equals()"), doesn't know anything about those fields > yet! It will think objects are not equal when they really are. > > So you have to override 'hashCode()', too, using the same fields, so > that its result are consistent with 'equals()': > > @Override public int hashCode() > { > return owner.hashCode() * 31 + color.hashCode(); > } > Just curious: why multiply the owner.hashCode() by 31? There's no significance to the 31 is there? Why not just add the two hashCodes together without multiplying one of them first? That would be just as good, right? > Since 'compareTo()' also makes claims about equality, it must agree > with the other two methods when it exists. > > Since the fields that determine equality identify the value by > definition, they should determine the 'toString()' result also: > > @Override public String toString() > { > assert owner != null && color != null; > return '{'+ owner +", "+ color + '}'; > } > > As you can see, 'toString()' can include additional information, but > it must show what identifies the value. > That makes perfect sense to me! -- Novice