Why is == true for some Integer objects? [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Integer wrapper objects share the same instances only within the value 127?
I have copied the following program snippet from the Khalid Mughal SCJP, but I am unable to
understand the output.
public class RQ200_60 {
public static void main(String[] args) {
Integer i = -10;
Integer j = -10;
System.out.print(i==j); // output: true -- why true?
System.out.print(i.equals(j)); // output: true
Integer n = 128;
Integer m = 128;
System.out.print(n==m); // output: false
System.out.print(n.equals(m)); // output: true
}
}
The above program giving output true for the first print statement but it supposed to give false because it is reference comparison with == relational operator. But third print gives false and I don't understand this inconsistency.
Explanations are greatly appreciated!

In the first case, both the objects i and j are pointing to the same cached object. By default, the range between -128 and 127 are cached as Integer Object. We can increase the range using JVM arguments

The answers about caching are correct. However, if you go...
Integer i = new Integer(10);
Integer j = new Integer(10);
...then you avoid the caching and the results will be what you expected.

Integer objects may be cached for the ones that represent a value close to 0. (The specification for the implementation may tell you some details). This is presumably to save memory (values close to 0 are common, and it would waste a lot of memory to make a new object for every variable with the same value).
== checks whether two things are the same object; you may or may not have the same Integer object for any two given variables with the same value. You are not supposed to check with == because you are not supposed to care whether it is the same object; it is the value of an Integer that matters, not its identity.

Here in this case the Integer i and Integer j holding the integer values which are in range of integer, range of an Integer is -128 to 128, and Integer n and Integer m exceeds the range of Integer

Related

In java equal and == behaviour [duplicate]

This question already has answers here:
Java: Integer equals vs. ==
(7 answers)
Closed 8 years ago.
Please can you explain the below behaviour.
public class EqAndRef {
public static void main(String[] args) {
Integer i = 10;
Integer j = 10;
Double a = 10D;
Double b = 10D;
System.out.println(i.equals(j));
System.out.println(i == j);
System.out.println(a.equals(b));
System.out.println(a == b);
}
}
Output on jdk 6
true
true
true
false
why a==b is false and i==j not false?
The Integers i and j are constructed (via auto boxing) from integer literals from the range –128 to 127 and thus are guaranteed to be pooled by the JVM so the same object (see flyweight pattern) is used for them. Hence, they compare identical by object references.
For the Doubles a and b on the other hand, no such pooling guarantee exists and, in your case, you got two different objects that did not compare identical.
Using == to compare objects if you don't mean to check identity is to be considered suspect and should be avoided. The equals methods of both types are overridden to compare the boxed values (as opposed to object identity) which is why they return true in both cases (and should be used).
Initialize the Integers the following way then you will get the difference as #5gon12eder said
The Integer s i and j are constructed (via auto boxing) from integer literals from the range –128 to 127 which are guaranteed to be pooled by the JVM so the same object (see flyweight pattern ) is used for them. Hence, they compare equal by object references.
try this code to initialize your integers
Integer i = new Integer(10);
Integer j = new Integer(10);

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

How can "a <= b && b <= a && a != b" be true? [duplicate]

This question already has answers here:
How to make loop infinite with "x <= y && x >= y && x != y"?
(4 answers)
How can i define variables to make an infinity while loop with these conditions? [closed]
(4 answers)
Closed 9 years ago.
Here is the code i have to figure it out how is it possible. I have a clue but i do not know how to do it. I think it is about negative and positive numbers and maybe the variable modifiers as well. I am a beginner i looked the solution everywhere but i could not find anything usable.
the question is that: You need to declare and initialize the two variables. The if condition must be true.
the code:
if( a <= b && b <= a && a!=b){
System.out.println("anything...");
}
I appreciate you taking the time.
This is not possible with primitive types. You can achieve it with boxed Integers:
Integer a = new Integer(1);
Integer b = new Integer(1);
The <= and >= comparisons will use the unboxed value 1, while the != will compare the references and will succeed since they are different objects.
This works too:
Integer a = 128, b = 128;
This doesn't:
Integer a = 127, b = 127;
Auto-boxing an int is syntactic sugar for a call to Integer.valueOf(int). This function uses a cache for values less than 128. Thus, the assignment of 128 doesn't have a cache hit; it creates a new Integer instance with each auto-boxing operation, and a != b (reference comparison) is true.
The assignment of 127 has a cache hit, and the resulting Integer objects are really the same instance from the cache. So, the reference comparison a != b is false.
Another rare case for class-variables may be that another thread could change the values of a and b while the comparison is executing.

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