• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Strange Behaviour Of Wrapper Class

 
Sanket Meghani
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello EveryOne,

I was just playing around the wrapper classes and observed some unexpected behaviour.

public class HelloWorld
{
public static void main( String args[] )
{
Integer i1 = 100;
Integer i2 = 100;

System.out.println( "i1 == i2 : " + ( i1 == i2 ) );
}
}

Output of the above code is unexpected with different values of i1 and i2.

For the current values ( i1 = 100 and i2 = 100 ) the output is : "i1 == i2 : true"

But for the following code,

public class HelloWorld
{
public static void main( String args[] )
{
Integer i1 = 1000;
Integer i2 = 1000;

System.out.println( "i1 == i2 : " + ( i1 == i2 ) );
}
}

the output is "i1 == i2 : false"

From different conbinations I have observed that in the above code for values of i1 and i2 between -128 to 127 ( range of byte ), i1 == i2 evaluates to true and for other values i1 == i2 evaluates to false.

What could be the reason behind this behaviour?

Thank You,
Sanket Meghani.
 
Peter Chase
Ranch Hand
Posts: 1970
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Advanced question? Not really.

First thing to say is that one should not be comparing Integer objects with == and expecting it to tell you whether they have equal numeric values. Use equals() for that.

When you use autoboxing to wrap int constants in Integer objects, you normally get a new Integer object. Thus, two autoboxings of the same value get different Integer objects, and == gives false (but equals() gives true, of course).

The JVM (or is it the compiler, I dunno) may use canonical cached objects for small values. That saves it from repeatedly creating new Integer objects for common values like -1, 0, 1, 2 etc. When this happens, two autoboxings of the same numeric value actually get the same object, so == tests true.

I think this is an internal implementation detail of a JVM, and I hope it is not standardised. Certainly, anyone who wrote a program that depended on this should be forced to write Perl, or whacked in the head (which would render them ideal for Perl programming...).
[ August 03, 2007: Message edited by: Peter Chase ]
 
David O'Meara
Rancher
Posts: 13459
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OUch, and then Peter told us what he really thought of Perl programmers
 
David O'Meara
Rancher
Posts: 13459
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, and coming back to the original question, since I got distracted: as Peter said, the unexpected behaviour is in the first example, not the second, and you should always be using .equals() regardless.
Also note that in practice you won't know the value of the variable (otherwise why make it variable?) and therefore you wouldn't be counting on the behaviour seen anyway.
 
Peter Chase
Ranch Hand
Posts: 1970
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by David O'Meara:
OUch, and then Peter told us what he really thought of Perl programmers


Or substitute the brain-damaged language (other than Java, of course) of your choice.
 
Joanne Neal
Rancher
Posts: 3742
16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Peter Chase:

I think this is an internal implementation detail of a JVM, and I hope it is not standardised.


I'm afraid it is. See Section 5.1.7 of the JLS.
 
Ulf Dittmer
Rancher
Posts: 42968
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Autoboxing an int to an Integer happens using the Integer.valueOf method, which does cache a limited range of Integer objects.

If the code had been

then two different objects would have been created, regardless of the argument.
 
Peter Chase
Ranch Hand
Posts: 1970
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Joanne Neal:
I'm afraid it is. See Section 5.1.7 of the JLS.


Oh dear. Well, people still shouldn't depend on it, IMHO.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would say it's partly specified in the JLS. That is, the JLS does specify that for all int values in the range -128 to 127, identical values must autobox to the same wrapper. However they do not specify exactly what happens outside this range. It would be perfectly legal for a particular JDK implementation to cache a larger range of wrapper values. So while you could depend on the fact that i1 == i2 when both are set to 100, you should not depend on the fact that i1 != i2 when both are set to 1000. It may be true for most (perhaps all) current JDKs, but it need not be true always.

Note that in current JDK implementations, Long wrappers are cached in the range -128 to 127, even though the JLS does not require this. So there is one example where the JDK exceeds the requirements of the JLS. Others may or may not occur in the future.

Overall though I would agree with Peter that even if some aspects of this behavior are guaranteed, it's probably a bad idea for programmers to rely on it. If only because this is the sort of trivia that's hard for programmers to remember, and other people reading your code may not be aware of it. Better to just avoid using == at all, where object wrappers are concerned.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic