File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes Autoboxing doubt Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Autoboxing doubt" Watch "Autoboxing doubt" New topic
Author

Autoboxing doubt

Mansukhdeep Thind
Ranch Hand

Joined: Jul 27, 2010
Posts: 1157

Hi

I am trying out the following code snippet:



It gives the output :

different objects
meaningfully equivalent

while if I change the value of i1 and i2 to 10, I get the output:

same object
meaningfully equivalent

I understood the i1.equals(i2) check working in both cases. But why is there a different outcome for the check of (i1==i2) in two cases where only difference being the values of i1 and i2 have been changed? They are still equal though. Aren't they? For 1000, i1!=i2 and for 10 i1==i2. What is going on here? Also, i1==i2 returns true ONLY till 127. 128 onwards i1!=i2 is true. Why this sort of peculiar behavior?

~ Mansukh
meeta gaur
Ranch Hand

Joined: Dec 05, 2012
Posts: 305

two instances of the following wrapper objects will always be = = when their primitive values are the same:

Boolean

Byte

Character from \u0000 to \u007f (7f is 127 in decimal)

Short and Integer from -128 to 127



My one regret in life is that I am not someone else.
- Woody Allen
Stevens Miller
Ranch Hand

Joined: Jul 26, 2012
Posts: 523
    
    3

The behavior you are seeing, Mansukhdeep , is from Section 5.1.7 of the Java language specification. It adds this oblique explanation:

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 char and short values, as well as int and long values in the range of -32K to +32K.


Note that last bit, which says you can't rely on any given range of numbers to be wrapped into objects that do or do not equate (other than the minimum ranges the spec requires will equate). Apparently, this is an optimization in contemplation of the notion that most numbers are in those ranges. That is, you tend to use the number "1" a lot more often than the number, "8,345,886," so there's a performance gain in having just one "1" stored in an Integer to represent every single instance of an Integer object that wraps a "1." Or so it seems.

This may seem peculiar, as you say. For what it is worth, I have grudgingly come to realize that most of the features of Java that, at first, seem kind of nutty to me, ultimately prove themselves to be the product of decisions made by people who actually knew what they were doing. (A jaw-dropping exception, of course, is the omission of unsigned data types, which I am told will not be appearing in any version of the language during my current incarnation.)

I tend to take this particular aspect of the language as an indication that testing objects for equality with == is typically not what I want to do, but your mileage may vary.
Mansukhdeep Thind
Ranch Hand

Joined: Jul 27, 2010
Posts: 1157

Stevens Miller wrote:The behavior you are seeing, Mansukhdeep , is from Section 5.1.7 of the Java language specification. It adds this oblique explanation:

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 char and short values, as well as int and long values in the range of -32K to +32K.


Note that last bit, which says you can't rely on any given range of numbers to be wrapped into objects that do or do not equate (other than the minimum ranges the spec requires will equate). Apparently, this is an optimization in contemplation of the notion that most numbers are in those ranges. That is, you tend to use the number "1" a lot more often than the number, "8,345,886," so there's a performance gain in having just one "1" stored in an Integer to represent every single instance of an Integer object that wraps a "1." Or so it seems.

This may seem peculiar, as you say. For what it is worth, I have grudgingly come to realize that most of the features of Java that, at first, seem kind of nutty to me, ultimately prove themselves to be the product of decisions made by people who actually knew what they were doing. (A jaw-dropping exception, of course, is the omission of unsigned data types, which I am told will not be appearing in any version of the language during my current incarnation.)

I tend to take this particular aspect of the language as an indication that testing objects for equality with == is typically not what I want to do, but your mileage may vary.


Hmm.. Off the record, what is meant by unsigned data types?
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7892
    
  21

meeta gaur wrote:two instances of the following wrapper objects will always be = = when their primitive values are the same:
Boolean
Byte
Character from \u0000 to \u007f (7f is 127 in decimal)
Short and Integer from -128 to 127

That is NOT true unless autoboxing or valueOf() was used to create the wrapper objects in question.

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Stevens Miller
Ranch Hand

Joined: Jul 26, 2012
Posts: 523
    
    3

Mansukhdeep Thind wrote:Hmm.. Off the record, what is meant by unsigned data types?

No need to go off the record. An unsigned data type is, in the most general sense, any data type that lacks a sign. As a more practical matter, it is typically an integer data type that stores values from zero to some maximum positive value, almost always reflective of the maximum value that can be stored in a base-two number of eight, sixteen, thirty-two, or sixty-four digits, because these are the natural storage limits of machine words of one, two, four, and eight bytes.

An unsigned byte, for example, if it existed in Java, would stored every value on the range [0, 255]. An unsigned short would cover the range [0, 65535], and so on.

A lot of the work I do involves images, which are very commonly represented as rectangular arrays of pixels, with each pixel represented numerically as three unsigned bytes, one each for red, green, and blue, with 0 indicating least amount of each color, and 255 representing the greatest amount of each color. Java has some great support for manipulating images, but if you want to operate on those pixel values, you either have to store them in some larger primitive (often requiring that you cope with negative values as you do so, unless you have some tricky way of copying the bytes as data, rather than as numbers, if that distinction means anything to you), or else you have to apply some tedious tests to your math operations to find out if the results wrapped around from below 128 to above 127 (and, hence, in Java, became negative).

I read an article about a year ago that says the early language designers felt that programmers didn't really understand unsigned integral primitives. As the former head of the three-dimensional commercial production department at a computer graphics lab whose programmers include many who have gone on to work at places like Pixar and LucasFilm, I can tell you that view is rather deeply flawed. However (and someone with better knowledge of the JVM should chime in here), I have heard that adding unsigned types to Java would be a major overhaul, owing for some reason to the nature of the JVM. That last part may be a false legend, and, indeed, the first bit (about us dumb ol' C programmuhs not bein' able to handle, uhhhh, unsigned numbahs) may be baldersdash as well. What is absolute, hard, undeniable fact, however, is that Java's lack of unsigned integral primitives is a major pain in my backside.
meeta gaur
Ranch Hand

Joined: Dec 05, 2012
Posts: 305

Winston Gutkowski wrote:
meeta gaur wrote:two instances of the following wrapper objects will always be = = when their primitive values are the same:
Boolean
Byte
Character from \u0000 to \u007f (7f is 127 in decimal)
Short and Integer from -128 to 127

That is NOT true unless autoboxing or valueOf() was used to create the wrapper objects in question.

Winston


Yea, we're discussing here wrapper classes.

true
false
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7892
    
  21

meeta gaur wrote:Yea, we're discussing here wrapper classes.

That doesn't alter the fact that, without qualification, your statement is wrong:
returns false; and the only factory method that is documented to return a cached value is valueOf(int).

That doesn't mean that others, such as parsetInt() or decode(), don't; simply that you can't rely on it.

Indeed, valueOf(String) specifically says that it:
"returns an Integer object equal to the value of: new Integer(Integer.parseInt(s))"

Winston
Mansukhdeep Thind
Ranch Hand

Joined: Jul 27, 2010
Posts: 1157

Stevens Miller wrote:
Mansukhdeep Thind wrote:Hmm.. Off the record, what is meant by unsigned data types?

No need to go off the record. An unsigned data type is, in the most general sense, any data type that lacks a sign. As a more practical matter, it is typically an integer data type that stores values from zero to some maximum positive value, almost always reflective of the maximum value that can be stored in a base-two number of eight, sixteen, thirty-two, or sixty-four digits, because these are the natural storage limits of machine words of one, two, four, and eight bytes.

An unsigned byte, for example, if it existed in Java, would stored every value on the range [0, 255]. An unsigned short would cover the range [0, 65535], and so on.

A lot of the work I do involves images, which are very commonly represented as rectangular arrays of pixels, with each pixel represented numerically as three unsigned bytes, one each for red, green, and blue, with 0 indicating least amount of each color, and 255 representing the greatest amount of each color. Java has some great support for manipulating images, but if you want to operate on those pixel values, you either have to store them in some larger primitive (often requiring that you cope with negative values as you do so, unless you have some tricky way of copying the bytes as data, rather than as numbers, if that distinction means anything to you), or else you have to apply some tedious tests to your math operations to find out if the results wrapped around from below 128 to above 127 (and, hence, in Java, became negative).

I read an article about a year ago that says the early language designers felt that programmers didn't really understand unsigned integral primitives. As the former head of the three-dimensional commercial production department at a computer graphics lab whose programmers include many who have gone on to work at places like Pixar and LucasFilm, I can tell you that view is rather deeply flawed. However (and someone with better knowledge of the JVM should chime in here), I have heard that adding unsigned types to Java would be a major overhaul, owing for some reason to the nature of the JVM. That last part may be a false legend, and, indeed, the first bit (about us dumb ol' C programmuhs not bein' able to handle, uhhhh, unsigned numbahs) may be baldersdash as well. What is absolute, hard, undeniable fact, however, is that Java's lack of unsigned integral primitives is a major pain in my backside.


Looks like you are certainly having a hard time sir. Thank you for your answer.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7892
    
  21

Stevens Miller wrote:What is absolute, hard, undeniable fact, however, is that Java's lack of unsigned integral primitives is a major pain in my backside.

Actually, you do: - char - and it works just as you'd expect an unsigned short to, except for display. For example:prints out
65345
65025
The problem is that without those final casts, it attempts to print it out as a character.

I suspect there's also a lot of promotion to int going on behind the scenes; but that would be the case for any smaller primitive.

Winston

Terry Tucker
Greenhorn

Joined: Jan 21, 2013
Posts: 22

Here is something interesting related to this discussion. If you use the new operator, the code behaves like you expect with the output being "i3 != i4"; however, if you just assign with the = operator, the output is "i3 == i4".
Ishan Pandya
Ranch Hand

Joined: Feb 06, 2012
Posts: 221

Go forward and read this link Cached Objects

thanks.


OCPJP
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39044
    
  23
Terry Tucker wrote: . . . If you use the new operator, the code behaves like you expect with the output being "i3 != i4"; however, if you just assign with the = operator, the output is "i3 == i4".
You are not assigning 10 there. You are boxing an int into an Integer object. It is equivalent to assigning i3 to Integer.valueOf(10);
The reason you get true from the == operator has already been explained in this thread. This thread also explains why such behaviour is unpredictable and unreliable; you should always avoid the == operator.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39044
    
  23
Ishan Pandya wrote:Go forward and read this link Cached Objects

thanks.
I have changed that link because it didn’t say that the cache is not a fixed size.
Ishan Pandya
Ranch Hand

Joined: Feb 06, 2012
Posts: 221

thaks Ritchie i too will have a look at that link.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39044
    
  23
It’s really interesting … except the bit I wrote.
And, “you’re welcome
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39044
    
  23
Stevens Miller,
Your post was moved to a new topic.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39044
    
  23
This thread continues on the Java in General forum. I moved it because it seemed to change subject halfway through.
 
GeeCON Prague 2014
 
subject: Autoboxing doubt