This week's book giveaway is in the OCPJP forum. We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line! See this thread for details.
I've been studying for the 1.5 programmer's cert and I in my study guide I came across something I thought very interesting...
What would be the output of the following:
I was very surprise to find out that in the case of i3 == i4 the result would be true!
The book (by K Sierra and B Bates) mentions the reasoning as:
In order to save memory, two instances of the following wrapper objects will always be == when their primitive values are the same:
Character from \u0000 to \u007f (7f is 127 in decimal)
Short and Integer from -128 to 127
I think this behavior of Java is a bit lame. Either have == always compare the values when it comes to the wrapper objects that are numbers or Boolean or else stick to having it always comparing references. What even makes it worse is that for the wrapper Integer (and I'm assuming Double and Float) the value is only compared if it fits into a byte - not even the value that would be represented by its primitive counterpart (int, double, float). [ October 16, 2006: Message edited by: Rick Reumann ]
This is the discussion from the Java Language Specification Section 5.1.7
Ideally, boxing a given primitive value p, would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. The implementation may cache these, lazily or eagerly.
For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part. This would allow (but not require) sharing of some or all of these references.
This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. Less memory-limited implementations might, for example, cache all characters and shorts, as well as integers and longs in the range of -32K - +32K.
Sun is sacrificing generality and othoganality for convinience.
The concepts of regularity are not sacrosanct, but is it wise to further muddy the language by having different behaviors for different contexts in a given construct?
I think Java is going the C++ route, just tossing anything and everything into the pot. I do prefer C++ over Java but am distressed at the way the languages have progressed. Which is why I have been getting into python lately. I just hope it stays clean as it moves forward.
[Rick]: Either have == always compare the values when it comes to the wrapper objects that are numbers or Boolean or else stick to having it always comparing references
Um, it is always comparing the references. It's just that within the specificed ranges, instances are cached and reused for autoboxing. This means that for example a 1 always autoboxes to the same Integer instance. Which does lead to some strange behavior, but ultimately it's just another example of the general rule: don't use == to compare reference objects unless you're sure you really want to compare object identity, and know exactly what that entails. This is much like the way two identical Strings may or may not turn out to be the same instance, depending on whether the String pool was involved in their creation. Which is also confusing, but people learn to avoid it. The problem here is just that autoboxing is still new to many people, and its transparency means that people often don't realize what is going on.
Now if we were designing a new language, I much prefer what Groovy did, which is to define == as always meaning an equals() comparison (with appropriate null check) when dealing with reference objects. The rare cases where identity comparison is really desired are handled with a new operator, ===. But for standard Java, we're stuck with a certain amount of ugliness from retroactive compatibility with design decisions made over a decade ago. [ October 16, 2006: Message edited by: Jim Yingst ]
"I'm not back." - Bill Harding, Twister
Joined: Apr 03, 2001
Originally posted by Jim Yingst:
Um, it is always comparing the references. It's just that within the specificed ranges, instances are cached and reused for autoboxing. This means that for example a 1 always autoboxes to the same Integer instance.
Wow, very interesting, thanks a lot of clarifying this for me. I thought it was actually comparing the value behind the scenes.