Integer class in Java [duplicate] - java

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 can't figure out why the output is different.
The output is same only in the range -128 to 127.
public class Check {
public static void main(String[ ] args) {
Integer i1=122;
Integer i2=122;
if(i1==i2)
System.out.println("Both are same");
if(i1.equals(i2))
System.out.println("Both are meaningful same");
}
}
Output:
Both are same
Both are meaningful same
public class Check {
public static void main(String[] args) {
Integer i1=1000;
Integer i2=1000;
if(i1==i2)
System.out.println("Both are same");
if(i1.equals(i2))
System.out.println("Both are meaningful same");
}
}
Output:
Both are meaningful same

You've encountered a caveat in the Java language where autoboxing for "small" values has a slightly different rule than autoboxing. ("Small" in this case means a number in the range of 127 to -128, as in a signed byte in C.) From JLS 5.1.7 Boxing Conversion:
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.
(Emphasis is mine.)
In the second example (where i1=i2=1000), the if(i1==i2) comparison results in false because the value of both objects is greater than 127. In that case == is a referential comparison, i.e. checking to see if the objects are actually the same object.

Related

Why is the output of following code different in the two print statements? [duplicate]

class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}
Output:
false
class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}
Output:
true
Note: Numbers between -128 and 127 are true.
When you compile a number literal in Java and assign it to a Integer (capital I) the compiler emits:
Integer b2 =Integer.valueOf(127)
This line of code is also generated when you use autoboxing.
valueOf is implemented such that certain numbers are "pooled", and it returns the same instance for values smaller than 128.
From the java 1.6 source code, line 621:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
The value of high can be configured to another value, with the system property.
-Djava.lang.Integer.IntegerCache.high=999
If you run your program with that system property, it will output true!
The obvious conclusion: never rely on two references being identical, always compare them with .equals() method.
So b2.equals(b3) will print true for all logically equal values of b2,b3.
Note that Integer cache is not there for performance reasons, but rather to conform to the JLS, section 5.1.7; object identity must be given for values -128 to 127 inclusive.
Integer#valueOf(int) also documents this behavior:
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.
Autoboxing caches -128 to 127. This is specified in the JLS (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.
A simple rule to remember when dealing with objects is - use .equals if you want to check if the two objects are "equal", use == when you want to see if they point to the same instance.
Using primitive data types, ints, would produce true in both cases, the expected output.
However, since you're using Integer objects the == operator has a different meaning.
In the context of objects, == checks to see if the variables refer to the same object reference.
To compare the value of the objects you should use the equals() method
E.g.
b2.equals(b1)
which will indicate whether b2 is less than b1, greater than, or equal to (check the API for details)
It is memory optimization in Java related.
To save on memory, Java 'reuses' all the wrapper objects whose values
fall in the following ranges:
All Boolean values (true and false)
All Byte values
All Character values from \u0000 to \u007f (i.e. 0 to 127 in decimal)
All Short and Integer values from -128 to 127.
Have a look at the Integer.java, if the value is between -128 and 127, it will use the cached pool, so (Integer) 1 == (Integer) 1 while (Integer) 222 != (Integer) 222
/**
* 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.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* #param i an {#code int} value.
* #return an {#code Integer} instance representing {#code i}.
* #since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Other answers describe why the observed effects can be observed, but that's really beside the point for programmers (interesting, certainly, but something you should forget all about when writing actual code).
To compare Integer objects for equality, use the equals method.
Do not attempt to compare Integer objects for equality by using the identity operator, ==.
It may happen that some equal values are identical objects, but this is not something that should generally be relied on.
if the value is between -128 and 127, it will use the cached pool and this is true only when auto-boxing.
So you will have below:
public static void main(String[] args) {
Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b); // false. == compare two instances, they are difference
System.out.println(a.equals(b)); // true. equals compares the value
Integer a2 = 100;
Integer b2 = 100;
System.out.println(a2 == b2); // true. auto-boxing uses cached pool between -128/127
System.out.println(a2.equals(b2)); // true. equals compares the value
Integer a3 = 129;
Integer b3 = 129;
System.out.println(a3 == b3); // false. not using cached pool
System.out.println(a3.equals(b3)); // true. equals compares the value
}
}
I wrote the following as this problem isn't just specific to Integer. My conclusion is that more often than not if you use the API incorrectly, you sill see incorrect behavior. Use it correctly and you should see the correct behavior:
public static void main (String[] args) {
Byte b1=127;
Byte b2=127;
Short s1=127; //incorrect should use Byte
Short s2=127; //incorrect should use Byte
Short s3=128;
Short s4=128;
Integer i1=127; //incorrect should use Byte
Integer i2=127; //incorrect should use Byte
Integer i3=128;
Integer i4=128;
Integer i5=32767; //incorrect should use Short
Integer i6=32767; //incorrect should use Short
Long l1=127L; //incorrect should use Byte
Long l2=127L; //incorrect should use Byte
Long l3=13267L; //incorrect should use Short
Long l4=32767L; //incorrect should use Short
Long l5=2147483647L; //incorrect should use Integer
Long l6=2147483647L; //incorrect should use Integer
Long l7=2147483648L;
Long l8=2147483648L;
System.out.print(b1==b2); //true (incorrect) Used API correctly
System.out.print(s1==s2); //true (incorrect) Used API incorrectly
System.out.print(i1==i2); //true (incorrect) Used API incorrectly
System.out.print(l1==l2); //true (incorrect) Used API incorrectly
System.out.print(s3==s4); //false (correct) Used API correctly
System.out.print(i3==i4); //false (correct) Used API correctly
System.out.print(i5==i6); //false (correct) Used API correctly
System.out.print(l3==l4); //false (correct) Used API correctly
System.out.print(l7==l8); //false (correct) Used API correctly
System.out.print(l5==l6); //false (correct) Used API incorrectly
}

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.

Autoboxing Unboxing Operator (!=) and (==) difference [duplicate]

This question already has answers here:
How != and == operators work on Integers in Java? [duplicate]
(5 answers)
Closed 9 years ago.
public class T1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2) System.out.println("different objects");
if(i1.equals(i2)) System.out.println("meaningfully equal");
}
}
O/P for this is:
different objects
meaningfully equal
Where as
public class T2 {
public static void main(String[] args) {
Integer i3 = 10;
Integer i4 = 10;
if(i3!=i4)System.out.println("Crap dude!!");
if(i3 == i4) System.out.println("same object");
if(i3.equals(i4)) System.out.println("meaningfully equal");
}
}
Produces Following O/P:
same object
meaningfully equal
I didn't understand why in class T2 if(i3!=i4) didn't get triggered I'm refering SCJP 1.6 but not able to understand.
Please help me.
This is because 10 is in between the range [-128, 127]. For this range == works fine since the JVM caches the values and the comparison will be made on the same object.
Every time an Integer (object) is created with value in that range, the same object will be returned instead of creating the new object.
See the JLS for further information.
Small integers get interned, meaning that there's only one instance of Integer for the given value.
This doesn't happen for large integers, hence the difference in behaviour between your two tests.
There is Integer pool for the numbers from -128 to 127 in java. JLS says
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.
anyway you can get double false with:
Integer n1 = -1000;
Integer n2 = -1000;
Integer p1 = 1000;
Integer p2 = 1000;
System.out.println(n1 == n2);
System.out.println(p1 != p2);
there is an option to set max size of this Integer pool
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the -XX:AutoBoxCacheMax=<size> option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
Integer are cached between range -128 to 127. so Integer in between the range(containing boundary values) will return the same reference..
like
Integer i3 = 127;
Integer i4 = 127;
Integer i5 = 128;
if(i3!=i4)System.out.println("Crap dude!!"); // same reference
if(i3 == i4) System.out.println("same object");
if(i3 != i5) System.out.println("different object");
output..
same object
different object
As '==' compares reference and 'equals' compares content. for more detail You may go to
Immutable Objects / Wrapper Class Caching

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.

Categories

Resources