Integer caching in Java with new operator - java

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).

Related

Integer object caching

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

When converting primitive data types to Objects, should you cast or create a new object?

This may break the discussion vs. answer rules, but I figure there's a preferred way of doing things.
--
Let's say you need to convert a primitive data type to an Object. Let's use int --> Integer as an example. You can do this by casting or straight up making a new Object. For example:
int a = 5; int b = 10;
Integer c = new Integer(a);
Integer d = (Integer) b;
Which is the better way to do it, a --> c or b --> d? I suspect they perform the same operation, so which one is usually used?
Thanks in advance.
Let's say you need to convert a primitive data type to an Object.
Let's use int --> Integer as an example. You can do this by casting or
straight up making a new Object. For example:
int a = 5; int b = 10;
Integer c = new Integer(a);
Integer d = (Integer) b;
Which is the better way to do it, a --> c or b --> d? I suspect they
perform the same operation, so which one is usually used?
Java compilers in versions 5 and later perform autoboxing to convert between a primitive value and it's corresponding boxed object. Autoboxing blurs, but does not erase, the distinction between primitive values and objects.
The following line is discouraged:
Integer c = new Integer(a);
This is because a new object is always created and prevents cached Integer objects from being reused.
This line is transformed by the Java compiler:
Integer d = (Integer) b;
Instead, this line becomes
Integer d = Integer.valueOf(b);
This is the code you would get if you omitted the cast from the assignment altogether. The primitive value is boxed into its corresponding object using the valueOf() function. This is the preferred way to assign primitive values to their objects because this allows the JVM to reuse frequently cached objects.
None of the above.
Use Integer.valueOf as it yields to significantly better space and time performance by caching frequently requested values.
From the docs of Integer.valueOf
Returns an {#code Integer} instance representing the specified
{#code int} value. If a new {#code Integer} instance is not
required, this method should generally be used in preference to
the constructor {#link #Integer(int)}, as this method is likely
to yield significantly better space and time performance by
caching frequently requested values.
But with autoboxing, the compiler will do it automatically for you.
Integer i = 1;
Which is a syntactic sugar for
Integer i = Integer.valueOf(1);
None of the above. You can lean on autoboxing in this scenario to take care of the casts.
That would make your code this:
int a = 5;
int b = 10;
Integer c = a;
Integer d = b;

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) );
}
}

what is difference between integer a = 5 and new Integer(5)?

if i write below code(in java):
Integer a =new Integer(5);
Integer b=new Integer(5);
if(a==b){
System.out.println("In ==");
}
if(a.equals(b)){
System.out.println("In equals");
}
My output is: "In equals"
But if i change first and second line to ->
Integer a =5;
Integer b=5;
then my o/p is:
In ==
In equals
So what is difference in creating a Integer object? How it gets created when we do Integer a =5?
Does it mean that a and b object refer to same object, if i create Integer a=5 and creates another object Integer b=5 ?
Integer a = 5; is called autoboxing, compiler converts this expression into actual
Integer a = Integer.valueOf(5);
For small numbers, by default -128 to 127, Integer.valueOf(int) does not create a new instance of Integer but returns a value from its cache. So here
Integer a = 5;
Integer b= 5;
a and b point to the same Object and a == b is true.
In Java, you should never use the new Integer, even though it is valid syntax it is not the best way to declare integers as you have found out. Use instead Integer.valueOf(int) This has multiple advantages.
You are not creating extra objects needlessly. Whenever you use the new operator you are forcing the vm to create a new object which is not needed in most cases. valueOf(int) will return a cached copy. Since Integer objects are immutable this works great. This means that you can use == though in practice you should use a null safe compare like in Apache ObjectUtils
The == operator tests for equality. References are only equal when they refer to the same object in memory. equals method ensures 2 object instances are 'equivalent' to each other.
Integer a = new Integer(5);
Integer b = a;
a == b; // true!
a.equals(b); // true
b = new Integer(5);
a == b; // false
a.equals(b); // true
Primitives are equal whenever their value is the same.
int a = 5; int b = a;
a == b; // true!
for primitive data types like int the equality operator will check if the variables are equal in value
for reference data types like your java.lang.Integer objects, the equality operator will check if the variables reference the same object. In the first case, you have two "new" and separate integer objects, so the references are different
Integer wrapper shares few properties of String class. In that it is immutable and that can be leveraged by using intern() like functionality.
Analyse this:
String a = "foo";
String b = "foo";
String c = new String("foo");
String d = new String("foo");
a == b //true
c == d //false
The reason is when JVM creates a new String object implicitly it reuses existing String object which has the same value "foo", as in case a and b.
In your case JVM implicitly auto-boxes the ints and re-uses existing Integer object. Integer.valueOf() can be used explicitly to re-use existing objects if available.
I believe when you create using new operator it creates object reference. In first case, there are two object references and they are not same but their value is same. That is not the situation in second case.

Why Java does not see that Integers are equal?

I have integers that are supposed to be equal (and I verify it by output). But in my if condition Java does not see these variables to have the same value.
I have the following code:
if (pay[0]==point[0] && pay[1]==point[1]) {
game.log.fine(">>>>>> the same");
} else {
game.log.fine(">>>>>> different");
}
game.log.fine("Compare:" + pay[0] + "," + pay[1] + " -> " + point[0] + "," + point[1]);
And it produce the following output:
FINE: >>>>>> different
FINE: Compare:: 60,145 -> 60,145
Probably I have to add that point is defined like that:
Integer[] point = new Integer[2];
and pay us taken from the loop-constructor:
for (Integer[] pay : payoffs2exchanges.keySet())
So, these two variables both have the integer type.
Check out this article: Boxed values and equality
When comparing wrapper types such as Integers, Longs or Booleans using == or !=, you're comparing them as references, not as values.
If two variables point at different objects, they will not == each other, even if the objects represent the same value.
Example: Comparing different Integer objects using == and !=.
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println(i == j); // false
System.out.println(i != j); // true
The solution is to compare the values using .equals()…
Example: Compare objects using .equals(…)
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println(i.equals(j)); // true
…or to unbox the operands explicitly.
Example: Force unboxing by casting:
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println((int) i == (int) j); // true
References / further reading
Java: Boxed values and equality
Java: Primitives vs Objects and References
Java: Wrapper Types
Java: Autoboxing and unboxing
If they were simple int types, it would work.
For Integer use .intValue() or compareTo(Object other) or equals(Object other) in your comparison.
In java numeric values within range of -128 to 127 are cached so if you try to compare
Integer i=12 ;
Integer j=12 ; // j is pointing to same object as i do.
if(i==j)
print "true";
this would work, but if you try with numbers out of the above give range they need to be compared with equals method for value comparison because "==" will check if both are same object not same value.
There are two types to distinguish here:
int, the primitive integer type which you use most of the time, but is not an object type
Integer, an object wrapper around an int which can be used to use integers in APIs that require objects
when you try to compare two objects (and an Integer is an object, not a variable) the result will always be that they're not equal,
in your case you should compare fields of the objects (in this case intValue)
try declaring int variables instead of Integer objects, it will help
The condition at
pay[0]==point[0]
expression, uses the equality operator == to compare a reference
Integer pay[0]
for equality with the a reference
Integer point[0]
In general, when primitive-type values (such as int, ...) are compared with == , the result is true if both values are identical. When references (such as Integer, String, ...) are compared with == , the result is true if both references refer to the same object in memory.
To compare the actual contents (or state information) of objects for equality, a method must be invoked.
Thus, with this
Integer[] point = new Integer[2];
expression you create a new object that has got new reference and assign it to point variable.
For example:
int a = 1;
int b = 1;
Integer c = 1;
Integer d = 1;
Integer e = new Integer(1);
To compare a with b use:
a == b
because both of them are primitive-type values.
To compare a with c use:
a == c
because of auto-boxing feature.
for compare c with e use:
c.equals(e)
because of new reference in e variable.
for compare c with d it is better and safe to use:
c.equals(d)
because of:
As you know, the == operator, applied to wrapper objects, only tests whether the objects have identical memory locations. The following comparison would therefore probably fail:
Integer a = 1000;
Integer b = 1000;
if (a == b) . . .
However, a Java implementation may, if it chooses, wrap commonly occurring values into identical objects, and thus the comparison might succeed. This ambiguity is not what you want. The remedy is to call the equals method when comparing wrapper objects.

Categories