aspose file tools*
The moose likes Beginning Java and the fly likes '==' operators with Wrapper class Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark " Watch " New topic
Author

'==' operators with Wrapper class

pranjal mishra
Greenhorn

Joined: Jan 08, 2009
Posts: 21
Hi I m in a little bit of confusion, I m studying Wrapper classes. The problem is with the == operator.

Output: Same Objects
Now here the int values are 100 for both i1&i2, now if I'll change it to 1000 the == operator won't show the same output like

Output: Different Objects


SCJP 1.5(95%)
Seetharaman Venkatasamy
Ranch Hand

Joined: Jan 28, 2008
Posts: 5575

from -128 to 127 , the Integer object compares the values
Saifuddin Merchant
Ranch Hand

Joined: Feb 08, 2009
Posts: 606

seetharaman venkatasamy wrote:from -128 to 127 , the Integer object compares the values


That does not sound correct.
The == operator always compares objects on the heap and not values. Hence there is no question of == comparing values.
You can verify this by


In this case the output is different object.

Trying to get to the original question, when we do
Integer i1 = 100; we are using auto boxing to convert the Integer/Short value to an Integer Object. I think the issue happens because of the way Java does the autoboxing though I agree it is weird!



Cheers - Sam.
Twisters - The new age Java Quiz || My Blog
pranjal mishra
Greenhorn

Joined: Jan 08, 2009
Posts: 21
seetharaman venkatasamy wrote:from -128 to 127 , the Integer object compares the values

well i think he is right upto some point.
Actually what i have figured out that if i'll assign the values to i1 and i2 till 127 the == will work, as soon as the value crosses 128 it won't work.
so for Short/Integer objects the == will always work if their primitives value will be between -128 to 127;

Saifuddin Merchant
Ranch Hand

Joined: Feb 08, 2009
Posts: 606

Explanation --> http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

Yep I was also a bit caught up, but for a real programming the rule is pretty simple,
Use == only for primitive types and reference equality
Use .equals for everything else!


Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 40052
    
  28
When you use Strings and have two Strings which are compile time constants, the JVM uses the same String objectTry that, and you find the two references point to the same String object.

When you use some wrapper objects, something rather similar happens. It happens for Integers; I think it happens for other types but can't remember the details. The JVM sets up a cache of objects for a restricted range of values, in the case of Integer where -128 <= i < 128, and reuses those objects if the same value is requested. So your two Integers for 100 will use the same object, and your two Integers for 1000 won't. The article quoted by Sam Mercs gives a good explanation.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14432
    
  23

seetharaman venkatasamy wrote:from -128 to 127 , the Integer object compares the values

No, it does not. But the reason why it seems to be like this, is because of the way that autoboxing and the method Integer.valueOf(int i) work.

First, when you use autoboxing, for example with a statement like this:

This is automatically translated by the Java compiler to the following:

So, when you use autoboxing, you are really implicitly calling the method Integer.valueOf(int i).

Now, the method Integer.valueOf(int i) contains an optimization. It has a cache containing Integer objects for all the values between -128 and 127. If you call the method with an int that is in this range, then the method does not create a new Integer object; instead, it returns one of the existing Integer objects in the cache. Creating a new object is relatively expensive, so using a cache like this makes programs run more efficiently.

That means that if you do something like this:

You are calling Integer.valueOf(int i) two times, with the same value 100, which is in the cache - so the method will return the same Integer object from the cache for both i1 and i2.

Since ==, when used on objects, checks if the two expressions on both sides of the == are the same object, the comparison i1 == i2 will return true.

Note that for numbers not in the range -128 to 127, Integer.valueOf(int i) will return a new Integer object.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 8 API documentation
pranjal mishra
Greenhorn

Joined: Jan 08, 2009
Posts: 21
Thanks a lot Jasper for such a wonderful explanation , Actually i had figured it out that for the range of -128 to 127 it works but what is the reason behind that now you told me.
Thanks a lot once again.
Seetharaman Venkatasamy
Ranch Hand

Joined: Jan 28, 2008
Posts: 5575

Excellent Jesper Young
Gaurav .Singh
Greenhorn

Joined: Apr 06, 2010
Posts: 8
thank you Jasper Young.. the reply was very useful
Doug Braidwood
Ranch Hand

Joined: Apr 04, 2010
Posts: 42
Nice answer! I knew about the -128 to 127 but not why!
Thanks


SCJP, SCWCD
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 40052
    
  28
Gaurav .Singh, welcome to the Ranch
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

The range is not always the same. You can change it with properties. However it is always at least -128 to 127


"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." --- Martin Fowler
Please correct my English.
marc weber
Sheriff

Joined: Aug 31, 2004
Posts: 11343

See JLS - Boxing Conversions...
If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.


"We're kind of on the level of crossword puzzle writers... And no one ever goes to them and gives them an award." ~Joe Strummer
sscce.org
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19785
    
  20

Wouter Oet wrote:The range is not always the same. You can change it with properties.

Really? Can you tell me which ones then? Because the source of Integer in Java 6 uses an array with hard coded bounds of -128 and 127.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 40052
    
  28
marc weber wrote:See JLS - Boxing Conversions
I knew it was in the JLS somewhere, but had forgotten where.Thank you.
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

Rob Prime wrote:
Wouter Oet wrote:The range is not always the same. You can change it with properties.

Really? Can you tell me which ones then? Because the source of Integer in Java 6 uses an array with hard coded bounds of -128 and 127.


C:\Users\Wouter\Documents\Temp>javac Test.java

C:\Users\Wouter\Documents\Temp>java Test
false

C:\Users\Wouter\Documents\Temp>java -Djava.lang.Integer.IntegerCache.high=2000 Test
true

Btw. There is no need for cynicism. Even if I where wrong. We're are human and we all make mistakes.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14432
    
  23

Interesting Wouter, I didn't know you could change the size of the Integer cache by a system property. I've looked in the source code of class Integer, and it does check if the value that you supply is larger than 127; if it's smaller, it's set to 127. So you can only make the cache larger, not smaller, than the standard value 127. (Which is understandable - if it weren't like that, it wouldn't conform to the JLS).
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 40052
    
  28
The JLS page quoted does say that it would be ideal to use a larger cache. Again, I had never seen that property used.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 19066
    
  40

I believe the property was added recently, so I am not surprised that it is not well known. For some reason, I remember a bug report, requesting this, only last year.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

That is correct. You're referring to this bug.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14432
    
  23

Aha, according to the bug report this is a new feature added in Java 6 update 14, so indeed quite recent.
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

What I find weird is that there is no such functionality for longs.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19785
    
  20

Wouter Oet wrote:Btw. There is no need for cynicism. Even if I where wrong. We're are human and we all make mistakes.

I wasn't being cynical. I was genuinely interested because as I said I couldn't find it in the source code. As Jesper noted it wasn't added until update 14, which explains why the source I used didn't have it.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19785
    
  20

Wouter Oet wrote:What I find weird is that there is no such functionality for longs.

It isn't present for byte, short or char either. Granted, byte wouldn't even need this functionality, but the others could have benefited from it too.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Interestingly, they seem to have backported this to the latest JDK 5 release as well, though it definitely wasn't in JDK 5 originally either.

As for why it's only in Integer - well, I guess ints are used so much more than any other type, they figured it was much more important to do it for ints than for anything else. Seems like it should have been easy to add it to the others anyway, but they didn't. They also only made it configurable in one direction, which is a little strange. The lower limit remains fixed at -128.

Perhaps each use of a config parameter in startup slows things down a tiny bit. For most applications this is irrelevant, but a few apps would benefit from a faster startup, so Sun/Oracle didn't want to slow these more than necessary. Though this still seems like the effect would be insignificant for current JVMs, note that Project Jigsaw is supposed to allow for faster startup of some apps (with fewer things to initialize). So maybe Sun/Oracle thought now would be a bad time to add to startup time in other areas.

Also of interest - longs aren't even required to be cached at all, but they do it anyway. Maybe it's an experiment that they didn't want to commit to. My guess is if a number is big enough that it requires a long, the chance that caching will help it is much lower than if it's an int. Sometimes it will help, sure, but I think it's another thing where they estimate the probable costs to probable benefits, and caching longs just isn't all that useful. Configuring the cache, even less so.
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

Rob Prime wrote:
Wouter Oet wrote:What I find weird is that there is no such functionality for longs.

It isn't present for byte, short or char either. Granted, byte wouldn't even need this functionality, but the others could have benefited from it too.

It is present for Byte. However due to a bad implementation not all the methods use this cache.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Hm, I thought the "it" Rob referred to was the new functionality of the cache being configurable. And as far as I can see, it isn't configurable. Now would there be any reason to make it configurable - the JLS already requires the cache to cover the full range of byte, so what else could you configure it to? I'm looking at java.lang.Byte.ByteCache.cache, which is final, and initialized to "new Byte[-(-128) + 127 + 1];" Are you talking about something else?
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

I'm talking about the cache itself. Not if it's configurable. The methods valueOf(String s) and valueOf(String s, int radix) of the Byte class do not use this cache which is a shame because autoboxing uses the first method.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19785
    
  20

This was also the case for Integer in the early updates of Java 6. There was clearly a "new Integer" in the other valueOf methods.

I did a file comparison of Byte's source of the latest update (19) and the previous version I had, with the old Integer source, and the two files are 100% identical. Long has changed so far as to use valueOf(long) in the other valueOf methods, but apart from Byte, Short and Character are also 100% identical.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Wouter Oet wrote:I'm talking about the cache itself. Not if it's configurable.

In that case, there is such functionality for longs. It's right there in the Long class, in the valueOf(long) method which is used by autoboxing. It's not described in the JLS, but then, neither is the configurability.
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

You're correct, I misinterpreted it. I look at the source code and a cache is also available for Character and Short.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: '==' operators with Wrapper class