Integer object caching - java

I read that "So when creating an object using Integer.valueOf or directly assigning a value to an Integer within the range of -128 to 127 the same object will be returned."
This is the reason why :-
Integer a=100;
Integer b=100;
if(a==b) // return true as both the objects are equal
But why not in this below case?
These two values are also in the range of 127 and -128 so according to the statement above this two will also return the same objects.
But the output here i am getting as "Not"
public static void main(String[] args) {
Integer a = 10;
Integer b = 12;
if(a == b)
System.out.println("same");
else
System.out.println("Not");
}
Can someone explain?

You're misunderstanding what "the same object will be returned" means.
So, comparison with == is actually comparing memory locations, and returns true only when the two variables hold the same object (i.e. stored at the same memory location).
Values between -128 to 127 are stored in the integer constant pool, which means that every 10 is the same 10 (i.e. the same memory location), every 12 is the same 12, etc. But it's not the case that all 10s are also 12s, which is what your question is unintentionally assuming.
Anyway, once you get outside of that range, each primitive int is a new object and is assigned to a new memory location outside of the constant pool.
You can test that with the following code:
public static void main(String[] args) {
Integer a = 1000;
Integer b = 1000;
if(a == b)
System.out.println("same");
else
System.out.println("Not");
}
That will print "Not", because a and b are two different objects stored in different memory locations.
And this is why you should compare things with .equals()

==
Checks whether both the references are pointing to the same memory location.
In the first case both values are same so they are pointing to the same location only one object will be created.
Integer a=100;
Integer b=100;
if(a==b) // return true as both the objects are equal
In the second case both values are different so they have different memory location for each so two objects will be created.
public static void main(String[] args) {
Integer a = 10;
Integer b = 12;
if(a == b)
System.out.println("same");
else
System.out.println("Not");
}

If you read the actual Java doc, you'll see a clearer description of what it is actually doing
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
As the Integer returned must represent the specified int value, there is no possible way that
Integer a = 10;
Integer b = 12;
System.out.println((a==b));
will print "true", as clearly the same object couldn't represent both values.
Edit:
For the sake of precision - The Java standard doesn't require that Integer autoboxing (assigning a primitive int to an Integer object) uses Integer.valueOf(), so it is quite possible that in a conforming Java implementation
Integer a = 10;
Integer b = 10;
System.out.println((a==b));
will print "false";

Simply They are not same object, those are two different Integer instances for to hold the given value, so as if the object are different it will always print Not

Related

Integer caching in Java with new operator

In the below class I have tried to compare the wrapper class with the primitive but the results are different.
I have checked the following links links:
The more interesting question is why new Object(); should be required to create a unique instance every time? i. e. why is new Object(); not allowed to cache? The answer is the wait(...) and notify(...) calls. Caching new Object()s would incorrectly cause threads to synchronize with each other when they shouldn't.
If there is a new object then how are a and c equal?
If b is equal to c and c is equal to a, then a should be equal to b. But in following case I got a != c.
Please explain.
class WrapperCompare {
public static void main (String args[]) {
Integer a = new Integer(10);
Integer b = 10;
int c=10;
System.out.println(b==c); //true
System.out.println(a==b); //false
System.out.println(a==c); //true
}
}
Update:
By referring to this link Integer caching.
Basically, the Integer class keeps a cache of Integer instances in the range of -128 to 127, and all autoboxing, literals and uses of Integer.valueOf() will return instances from that cache for the range it covers.
So in this case all statements should be true.
Explanation
When you compare Integer vs int with ==, it needs to convert the Integer to an int. This is called unboxing.
See JLS§5.1.8:
If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()
At that point, you are comparing int vs int. And primitives have no notion of instances, they all refer to the same value. As such, the result is true.
So the actual code you have is
a.intValue() == c
leading to a comparison of 10 == 10, both int values, no Integer instances anymore.
You can see that new Integer(...) indeed creates new instances, when you compare Integer vs Integer. You did that in a == b.
Note
The constructor new Integer(...) is deprecated. You should instead use Integer#valueOf, it is potentially faster and also uses an internal cache. From the documentation:
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
The caching is important to note here, since it yields to == being true again (for cached values):
Integer first = Integer.valueOf(10);
Integer second = Integer.valueOf(10);
System.out.println(first == second); // true
The caching is guaranteed for values between -128 and +127, but may also be used for others.
Also note that your b actually comes out of the cache, since
Integer b = 10;
// same as
Integer b = Integer.valueOf(10);
// and not
Integer b = new Integer(10);
So boxing goes through Integers cache (see JLS§5.1.7).

Why isn't Integer.MIN_VALUE equal to stored Integer.MIN_VALUE in variable?

I made an Interval class with the following fields:
...
private static final Integer MINF = Integer.MIN_VALUE;
Integer head,tail;
...
when I make an instance of this class, making this.head = Integer.MIN_VALUE, and I want to check if the value of head is equal to MINF, it says that they aren't equal.
Interval i = new Interval(Integer.MIN_VALUE,10);
System.out.println(i.toString()); //[-2147483648,10]
So I went ahead and tried to print the values,
public String toString() {
...
//What the hell?
System.out.println("MINF == Integer.MIN_VALUE: " + (MINF == Integer.MIN_VALUE)); //true
System.out.println("MINF == this.head: " + (MINF == this.head)); //false
System.out.println("Integer.MIN_VALUE == this.head: " + (Integer.MIN_VALUE == this.head)); //true
...
return "*insert interval in format*";
}
Which says
MINF == Integer.MIN_VALUE is true
MINF == this.head is false, although this.head = -2147483648
Integer.MIN_VALUE == this.head is true
Am I missing something for why the second one is false?
Integer is the wrapping class, child of Object and containing an int value.
If you use only the primitive type int, == does a numerical comparison and not an object address comparison.
Mind that Integer.MIN_VALUE of course is an int too.
You are missing the fact that when stored in Integer (that is, you store Integer.MIN_VALUE in two different integers) and using == between them, the comparison is not of the values, but of the objects.
The objects are not identical because they are two different objects.
When each object is compared to Integer.MIN_VALUE, since Integer.MIN_VALUE is an int, the object is autounboxed and compared using int comparison.
No one here has addressed the REASON why they're different objects. Obviously:
System.out.println(new Integer(10) == new Integer(10));
outputs false, for reasons that have been discussed to death in the other answers to this question and in Comparing Integer objects
But, why is that happening here? You don't appear to be calling new Integer. The reason is that:
Integer.MIN_VALUE returns an int, not an Integer.
You have defined MINF to be an Integer
Autoboxing uses valueOf. See Does autoboxing call valueOf()?
valueOf calls new Integer if the int is not in the integer cache,
The cache is only the values -128 -> 127 inclusive.
And that is why you are seeing the "two Integer objects are not == behavior", because of autoboxing. Autoboxing is also why equality does not appear to be transitive here.
You can fix this problem by instead using:
private static final int MINF = Integer.MIN_VALUE;
And, in general: don't use Integer for simple fields.; only use it as a generic type where you actually need the object.
You are using Integer objects. The use of == should be used as a comparison of individual primitive's values only. Since you used the Integer class rather than the primitive int then it is comparing the object's references between the two variables rather than their values.
Because MINF is a separate object to head you are receiving false for a direct comparison using ==.

equals only when put into variables

I have two values to be compared. They appear to be not equal when compared directly using the == operator, but equal after they are put into local variables. Could anyone tell me why?
The code is as follows:
(MgrBean.getByName(name1).getId() == MgrBean.getByName(name2).getId()),
//This one is false,
int a = MgrBean.getByName(name1).getId();
int b = MgrBean.getByName(name2).getId();
(a == b); //This one is true.
I believe your getId() is returning an Integer instead of int.
Integer is the wrapper class for int primitive type. If you compare object reference using ==, you are comparing if they are referring to same object, instead of comparing the value inside. Hence if you are comparing two Integer objects reference, you are not comparing its integer value, you are simply checking if that two reference is pointing to same Integer object.
However, if you use a primitive type to store that value (e.g. int a = ....getId()), there is auto-unboxing happening, and that wrapper object is converted to primitive type value, and comparing primitive type values using == is comparing the value, which do the work you expect.
Suggested further reading for you:
Primitive Type vs Reference Type in Java
Auto-boxing and unboxing in Java
The most misconception about Integer type happens everywhere including other answers here
Suppose you have two integers defined as follows:
Integer i1 = 128
Integer i2 = 128
If you then execute the test (i1 == i2), the returned result is false. The reason is that the JVM maintains a pool of Integer values (similar to the one it maintains for Strings). But the pool contains only integers from -128 to 127. Creating any Integer in that range results in Java assigning those Integers from the pool, so the equivalency test works. However, for values greater than 127 and less than -128), the pool does not come into play, so the two assignments create different objects, which then fail the equivalency test and return false.
In contast, consider the following assignments:
Integer i1 = new Integer(1); // Any number in the Integer pool range
Integer i2 = new Integer(1); // Any number in the Integer pool range
Because these assignments are made using the 'new' keyword, they are new instances created, and not picked up from the pool. Hence, testing (i1== i2) on the preceding assignments returns false.
Here's some code that illustrates the Integer pool:
public class IntegerPoolTest {
public static void main(String args[]){
Integer i1 = 100;
Integer i2 = 100;
// Comparison of integers from the pool - returns true.
compareInts(i1, i2);
Integer i3 = 130;
Integer i4 = 130;
// Same comparison, but from outside the pool
// (not in the range -128 to 127)
// resulting in false.
compareInts(i3, i4);
Integer i5 = new Integer(100);
Integer i6 = new Integer(100);
// Comparison of Integers created using the 'new' keyword
// results in new instances and '==' comparison leads to false.
compareInts(i5, i6);
}
private static void compareInts(Integer i1, Integer i2){
System.out.println("Comparing Integers " +
i1 + "," + i2 + " results in: " + (i1 == i2) );
}
}

different output for same code in Java

I am new to java. I know somewhat about the wrapper classes and primitive datatypes, but what I have come across is surprising. On changing the values of the variables i and j from 1000 to 100, the output changes from false to true. I need to know the mechanism behind this.
class Demo{
public static void main(String[] args){
Integer i=1000,j=1000;
if(i==j)
System.out.println("true");
else
System.out.println("false");
}
}
the above code gives me "false" while..
class Demo{
public static void main(String[] args){
Integer i=100,j=100;
if(i==j)
System.out.println("true");
else
System.out.println("false");
}
}
the above code give me "true"
Caching in Wrapper Classes
Integer has internal cache for values ranging from -128 to 127.
So for numbers within this range, the same instance of Integer is returned. == compares by instance, and so the same instance is used for 100.
Source JDK 1.6:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Caching in wrapper classes Java
Purpose of Caching
The purpose is mainly to save memory, which also leads to faster code due to better cache efficiency.
Use .equals when comparing value, not identity
If you are comparing two Integers, you should use i.equals(j) just like you would do to correctly compare the value of Strings. Also keep in mind that any operation which will unbox an Integer places an implicit call to Integer.intValue(), so remember to make these calls carefully, knowing when your Integer might be null.
To compare the contents of objects (instead of their identity) use equals instead of ==. This will give consistent results.
Wrapper class Integer has internal cache for -127 to 127. So when you assign same values which are within this range same instance will be returned. For 1000 two different 'new'ed instances are returned giving false on == comparision.
If you use int instead of Integer, results will not be surprising. For consistent result with your approach, use equals() method instead of ==.

operator == differet behaviour on wrapper class object

can Any body explain me what is happeing in the output.
If == is use to compare two ref. variable it simply check its reference if they are same then it enter in if body, then why the hell
aa==bb is equal if creting static method valueOf() and ee==ff is not equal (which is ok) if creating its object using new keyword ?
static void main(String args[])
{
Integer aa = Integer.valueOf("12");
Integer bb = Integer.valueOf("12");
if(aa==bb)System.out.println("aa==bb");
if(aa!=bb)System.out.println("aa!=bb");
Integer ee = new Integer("12");
Integer ff = new Integer("12");
if(ee==ff)System.out.println("ee==ff");
if(ee!=ff)System.out.println("ee!=ff");
}
Output :
aa==bb
ee!=ff
The == comparator checks for object equality!
Since Integer.valueOf maintains a cache of Integer Objects with the value -128 to 127 valueOf(String) returns the cached object, thus the == comparance results in true.
Integer a1 = new Integer("12");
Integer b1 = new Integer("12");
//a1 == b1 returns false because they point to two different Integer objects
Integer aa = Integer.valueOf("12");
Integer bb = Integer.valueOf("12");
//aa == bb returns true because they point to same cached object
For the comparance of object values always use the .equals method, for primitives like int, long etc. you can use the == comparator.
Because Integer.valueOf maintains cache of integers from -128 to 127
Here is the source code of valueOf you can clearly see that it returns same object if Integer value is between -128 to 127
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
so your == returns true. If value is more than that then it will always return you false.
Integer aa = Integer.valueOf("1200");
Integer bb = Integer.valueOf("1200");
aa == bb --> false
You should always check equality using equals method
ee.equals(ff);
If you add another if with below
if (ee.equals(ff))
System.out.println("ee equals ff");
Output will be
ee equals ff
For ee and ff two objects of Integer are created on heap hence both of them are referencing different objects so they are not equal when using == operator.
new Integer("12") creates a new Integer object with value 12. No matter how times you do that you are creating a brand new object each time. That's why == doesn't work in the second case.
The JVM maintains a cache of the Integer objects for values that are believed to be used more frequently (-128 - 127). Integer.valueOf("12") behind the scene does the same thing (new Integer("12")), but before doing that it checks in that cache if for that value the object already exists in the cache, if it does then that's what it returns, otherwise it creates a new one, adds it to the cache and returns it. That's why == works in the first case.
Also, for objects, == should never be used for equality checks, instead they should be used only for identity checks (e.g. to see if two different variables are referring to the same object). For equality check always use the equals method.

Categories