Autoboxing Question [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Wrapper class and == operator
Saw this code in a website when i was learning about autoboxing..
Integer i1 = 1;
Integer i2 = 1;
// true
System.out.println(i1 == i2);
Integer i3 = -200;
Integer i4 = -200;
// false
System.out.println(i3 == i4);
I can understand why the 2nd comparison gives false (its comparing references). But why is it giving true for the first one ?

Because the first several Integer objects (from -128 to 127, inclusive, to be precise) are cached and reused by the JVM, so i1 and i2 are references to the same physical object.
This is also true to Long, Short and Byte btw. See this article for a more detailed explanation.

Boxing is guaranteed to use the same cached objects for a range of values.
Beyond that the JVM can use a larger cache, but it's not guaranteed. From the JLS section 5.1.7:
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.

Related

Integer comparison with == [duplicate]

This question already has answers here:
Integer wrapper objects share the same instances only within the value 127? [duplicate]
(5 answers)
Closed 8 years ago.
I was writing some test code and found one strange thing, and still confused how this is happening?
Integer i1 = 220;
Integer i2 = 220;
System.out.println(i1 == i2);
prints false as expected. But
Integer i1 = 20;
Integer i2 = 20;
System.out.println(i1 == i2);
prints true, but both are different references referring to different objects (I assume that).
How come second snippet prints true?
The == operator only works for Integer values between -128 and 127. That is why it doesn't work for 220 but does for 20. In general it is best to always use .equals() when comparing Integers and you should never rely on the == operator.
More information can be found here: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

Does == comparison use byte in ArrayList comparisons? [duplicate]

This question already has answers here:
How != and == operators work on Integers in Java? [duplicate]
(5 answers)
Closed 8 years ago.
In a program I was working on, I ran into a data storage issue, specifically related to ArrayLists. This is not the actual code I was testing, but it provides an example of what I mean.
public class test
{
public static void test()
{
ArrayList<Integer> bob = new ArrayList<Integer>();
bob.add(129);
bob.add(129);
System.out.println(bob.get(0) == 129 );
System.out.println(bob.get(1) == 129 );
System.out.println(bob.get(0) == bob.get(1) );
}
}
If you run it, you get, true, true, and false. The code recognizes that both are equal to 129 but for some reason returns false when it attempts to see if they are equal to each other. However, if you change the value to 127, it returns true, true, and true. Testing this multiple times for different values and you will see that the minimum value to receive true, true, and true is -128 and the maximum is 127. This is the interval for byte, which leads me to suspect that the == operation uses byte in this case.
What is interesting is that if you modify the code so that it reads
public class test
{
public static void test()
{
ArrayList<Integer> bob = new ArrayList<Integer>();
bob.add(129);
bob.add(129);
int a = bob.get(0);
int b = bob.get(1);
System.out.println(a == 129 );
System.out.println(b == 129 );
System.out.println(a == b );
}
}
it works just as intended. true, true, and true are outputted. Why does saving the values as int before the comparison change the outcome? Is it because if they are not saved, the comparison will use byte by default for the == comparison?
The answer lies in the caching mechanism of the primitive wrapper classes that Java employs.
In the case of an Integer, there's caching for the values between -128 to 127 (i.e. the value range of a byte).
This means that if you box any value between -128 to 127, you get a ready made instance from the cache. This is why the == operator works for those, as it compares the references rather than the values.
On the other hand, if you're using any other value, you'll get a fresh new instance per boxing, which means that the == operator will fail.
Here's the piece of code from the Integer class that's responsible for this:
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
Right, I just realized that I can explain this. Don't know what I was thinking earlier.
JLS, section 5.1.7:
If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1), or the boolean literal true or false (§3.10.3), or a character literal between '\u0000' and '\u007f' inclusive (§3.10.4), then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.
As 129 falls outside this range, you'll end up with two distinct Integer objects in indices 1 and 2, unless you configure the range yourself using JVM flags.
For the last comparison in the first bit of code: As ArrayList#get() returns an object of the type the ArrayList is parameterized with, that last comparison is comparing two Integer objects, and as the two objects are distinct, the result will be false. The first two comparisons result in the Integer objects being unboxed, because you're comparing an Integer wrapper to an int literal, so the results are as you expect.
The second bit of code works as you expect because you're comparing int literals, and those comparisons are more intuitive.
Autoboxing and unboxing are at work, this works -
bob.add(129); // Autoboxed to Integer
int a = bob.get(0); // primitive int a
int b = bob.get(1); // primitive int b
System.out.println(a == 129 ); // primitive to primitive
System.out.println(b == 129 ); // primitive to primitive
System.out.println(a == b ); // primitive to primitive
You could also use Integer.intValue(),
Integer a = bob.get(0);
Integer b = bob.get(1);
// Here you could omit one, but not both, calls to intValue()
System.out.println(a.intValue() == b.intValue()); // primitive to primitive
This is because first two comparisons are on int values because bob.get() is getting casted to int before comparison. in the third, comparison is on Objects and that is the reason you are getting false for values outside -128 to 127 because in this range values are cached.
Hope this helps.
Collections have 2 get methods that accept int and Integer with Integer collections, autoboxing is doing some internal magic to use the wrong method (Effective Java)
Use explicit boxing or unbox as necessary.
That's because the third test compares two objects because the (Integer object) return of the get() calls are not unboxed. The values for which the result is true are using cached singletons and therefore the same object, but outside of that range new and distinct objects are put into the list by auto-boxing.
Take note that this behavior could vary from JVM to JVM and version to version; on some JVMs it could even be dynamic based on some heuristic - for example, the system could conceivably look at available memory and cache 16 bit values instead of 8.

java: class Integer == operator strange behaviour [duplicate]

This question already has answers here:
Using == operator in Java to compare wrapper objects
(8 answers)
Integer wrapper class and == operator - where is behavior specified? [duplicate]
(2 answers)
Weird Integer boxing in Java
(12 answers)
Closed 9 years ago.
public class IntegerVsInt {
public static void main(String args[])
{
int a = 1;
int b = 1;
int c = a + b;
System.out.println(c);
System.out.println(a == b);
Integer x = 1;
Integer y = 1;
Integer z = x + y;
System.out.println(z);
System.out.println(x == y);
}
}
In the above code I am comparing two int's and two objects of type integer.
When you compare two int's
a == b
I would expect their values to be compared.
However when you compare two Integer's
x == y
I would expect the address of the two object to be compared and then return a false.
I get true in both the cases? Why is this behavior?
The == is testing whether the Integers are the same object. In java, certain small values are required to be cached, as well as others may optionally be cached, which is why the == Object reference evaluates to true.
The snippet from the JLS Spec 5.1.7
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
x == y
is true for values between -128 and 127 due to integer caching.
Try
Integer x = 130;
Integer y = 140;
Now compare and see the magic.
From language spec
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
Reason:
The behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. Less memory-limited implementations might.

How != and == operators work on Integers in Java? [duplicate]

This question already has answers here:
Why is 128==128 false but 127==127 is true when comparing Integer wrappers in Java?
(8 answers)
Closed 6 years ago.
The following code seemed really confusing to me since it provided two different outputs.The code was tested on jdk 1.7.
public class NotEq {
public static void main(String[] args) {
ver1();
System.out.println();
ver2();
}
public static void ver1() {
Integer a = 128;
Integer b = 128;
if (a == b) {
System.out.println("Equal Object");
}
if (a != b) {
System.out.println("Different objects");
}
if (a.equals(b)) {
System.out.println("Meaningfully equal.");
}
}
public static void ver2() {
Integer i1 = 127;
Integer i2 = 127;
if (i1 == i2) {
System.out.println("Equal Object");
}
if (i1 != i2){
System.out.println("Different objects");
}
if (i1.equals(i2)){
System.out.println("Meaningfully equal");
}
}
}
Output:
[ver1 output]
Different objects
Meaningfully equal.
[ver2 output]
Equal Object
Meaningfully equal
Why the == and != testing produces different results for ver1() and ver2() for same number much less than the Integer.MAX_VALUE? Can it be concluded that == checking for numbers greater than 127 (for wrapper classes like Integer as shown in the code) is totally waste of time?
Integers are cached for values between -128 and 127 so Integer i = 127 will always return the same reference. Integer j = 128 will not necessarily do so. You will then need to use equals to test for equality of the underlying int.
This is part of the Java Language Specification:
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
But 2 calls to Integer j = 128 might return the same reference (not guaranteed):
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.
Because small integers are interned in Java, and you tried the numbers on different sides of the "smallness" limit.
There exist an Integer object cache from -128 and up to 127 by default. The upper border can be configured. The upper cache border can be controlled by VM option -XX:AutoBoxCacheMax=<size>
You are using this cache when you use the form:
Integer i1 = 127;
or
Integer i1 = Integer.valueOf(127);
But when you use
Integer i1 = new Integer(127);
then you're guaranteed to get a new uncached object. In the latter case both versions print out the same results. Using the cached versions they may differ.
Java caches integers from -128 to 127 That is why the objects ARE the same.
I think the == and != operators when dealing with primitives will work how you're currently using them, but with objects (Integer vs. int) you'll want to perform testing with .equals() method.
I'm not certain on this, but with objects the == will test if one object is the same object or not, while .equals() will perform testing that those two objects contain equivalence in value (or the method will need to be created/overridden) for custom objects.

Integer wrapper objects share the same instances only within the value 127? [duplicate]

This question already has answers here:
Why is 128==128 false but 127==127 is true when comparing Integer wrappers in Java?
(8 answers)
Closed 8 years ago.
Here they are the same instance:
Integer integer1 = 127;
Integer integer2 = 127;
System.out.println(integer1 == integer2); // outputs "true"
But here they are different instances:
Integer integer1 = 128;
Integer integer2 = 128;
System.out.println(integer1 == integer2); // outputs "false"
Why do the wrapper objects share the same instance only within the value 127?
Because it's specified by Java Language Specification.
JLS 5.1.7 Boxing Conversion:
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
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.
The source of java.lang.Integer:
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);
}
Cheers!
BTW you can shorten your code to
System.out.println("Integer 127 == " + ((Integer) 127 == (Integer) 127));
System.out.println("Integer 128 == " + ((Integer) 128 == (Integer) 128));
for(int i=0;i<5;i++) {
System.out.println(
"Integer 127 system hash code " + System.identityHashCode((Integer) 127)
+ ", Integer 128 system hash code "+System.identityHashCode((Integer) 128));
}
prints
Integer 127 == true
Integer 128 == false
Integer 127 system hash code 1787303145, Integer 128 system hash code 202703779
Integer 127 system hash code 1787303145, Integer 128 system hash code 1584673689
Integer 127 system hash code 1787303145, Integer 128 system hash code 518500929
Integer 127 system hash code 1787303145, Integer 128 system hash code 753416466
Integer 127 system hash code 1787303145, Integer 128 system hash code 1106961350
You can see that 127 is the same object each time, whereas the object for 128 is different.
Because small values in the range [-128, 127] are cached and bigger values are not.
To wrap integers, Java uses http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html#valueOf%28int%29
Additionally to the other answers I want to add that == compares the object references only. Use .equals() instead:
Integer integer1=128;
Integer integer2=128;
if(integer1.equals(integer2))
System.out.println(true);
else
System.out.println(false);

Categories

Resources