This question already has answers here:
Integer wrapper class and == operator - where is behavior specified? [duplicate]
(2 answers)
Closed 8 years ago.
I am a novice Java programmer and came across a very weird scenario, as below.
public static void main(String[] args) {
Integer a = 500;
Integer b = 500;
// Comparing the values.
a <= b; // true
a >= b; // true
a == b; // false
// Reassigning the values
a = 50;
b = 50;
// Again comparing the values.
a <= b; // true
a >= b; // true
a == b; // true
}
My question is why do the results of a == b vary by varying values?
The answer to this question lies within the understanding of Autoboxing specified by Java programming language.
The variation in results of a == b happens because any integer between -128 to 127 are cached by the Integer class. When an int within this range is created it is retrieved from IntegerCache rather than creating a new Integer object.
Is this a bug? Of course not!
The Java class Integer is also called wrapper class because it provides an object that wraps an int primitive data type. In Java, comparing two value object is not straight forward. We should override the Object.equal method (and also the Object.hashCode) and use it to determine when two objects are equal. Using the == operator, in this case, we’re comparing the two physical object addresses. Java requires the new operator to create objects, which will be all stored on the JVM’s Heap. Local variables are stored on the JVM’s Stack, but they hold a reference to the object, not the object itself.
In first case when we check if a == b, we’re actually checking if both the references are pointing at the same location. Answer to this is NO!
But what happens when a & b are 50? To answer this we should have a look at the below Integer.valueOf method.
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
We are using the Autoboxing Java function through this Integer.valueOf method to compare a == b. With the aim of optimizing the resources use, the Integer class maintains a cache memory of Integer instances. This way, all the new Integer requests with a value between -128 and IntegerCache.high (configurable) will return an identical object allocated once. So, when we ask if a == b, we get true because, behind the scene, a and b are pointing to the same memory location.
Now another question arises: Does this approach involve in instance sharing problems? The answer fortunately is no, because Integer was defined as an immutable object and that means if you want to modify it, you have to get a new instance… exciting, isn’t it?
Shishir
Yes . Because values from a range of -127 to 128 will be stored in cache . so use equals and compare .
Java has interned the values from -128 to 127.
This is why you receive true when you compare two Integer objects in this range with ==.
Related
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 2 years ago.
Is c point to a or is c point to the same memory that a is pointing to?
Why does the following code print "We are equal"?
Thanks in advance
public static void main(String args[]) {
String a = "10";
String b = "10";
String c = a;
if(c.equals(b)) {
System.out.println("We are equal ");
}
else {
System.out.println("Not equal! ");
}
}
Java stores objects by reference... the reference just happens to be the value when we use primitives.
int is a primitive so
a == c => true
a == b => true
b == c => true
With Strings the situation is slightly different. Strings are effectively char arrays: char[] but are not considered primitive types in Java.. so:
"str1" == "str1" => false since you're comparing two object references now.
For this reason the Object class has the equals() method which allows you to compare reference objects (non-primitives) via something other than the object reference ID. The String (a subclass of Object.class) class overrides the equals method.
In your example (above) you say:
So why is ab==abc false. They are both pointing to same address.
This is incorrect. ab points to String that is "meowdeal" and abc points to a String that is also "meowdeal"... but crucially they are two distinct instances. Therefore:
ab==abc => false - here your checking for reference equality - are they the same object reference (no they are not)
ab.equals(abc) => true - here you're checking for string equality (is ab's "meowdeal" the same as abc's "meowdeal" - yes it is.
This is one of those curveball interview questions you might get from time to time so worth being aware of.
Specifically, in the case of object reference equality, what does the == operator do?
Does the comparison return true if the references evaluate to the same object address at the time of comparison? Or does it utilize the hashCode value of the two references to determine if the objects are the same?
To be very specific here, I would like to know what data structures managed by the JVM are referenced by the == operation for reference comparison. Does == rely on the OOP to perform reference comparison?
Unfortunately for me, the JLS does not define how the == operator must work. The Java API docs do not mention what == is supposed to do (they're for classes, right?)
PS: I was a bit intrigued by this question on hashcode uniqueness, and would prefer to know how the Sun JVM (or OpenJDK) implements the == operator.
The == operator just compares the references.
References in the JVM are just a standard object pointer. This works out to a single 32bit or 64bit integer value (depending on platform).
When you compare two object references, you're really just comparing two 32bit or 64bit integers, and if they're the same, you'll equate to equal. The integer values are a location in memory.
Because a reference is just a number, a reference comparison comes down to just comparing two numbers. No hash is needed.
The == operator compares object references to see if they are identical, i.e. they refer to the same object in memory.
The equals() method compares object references to see if they are equivalent, though not necessarily identical. The default implementation of equals() uses the == operator, but it often makes sense to override this behavior. For example, you might want two BankAccount references to be considered equivalent if they have the same account number, even if they are completely different objects.
The == operator returns true if the objects are the same object. There is not access to hashCode() or equals() here.
Try this to confirm:
public class Test {
static void testEqualEqual(Integer I0, Integer I1, boolean IsEquals) {
if(!(IsEquals == (I0 == I1)))
throw new AssertionError();
}
static void testEqual(Integer I0, Integer I1, boolean IsEquals) {
if(!(IsEquals == (I0.equals(I1))))
throw new AssertionError();
}
static void testHash(Integer I0, Integer I1, boolean IsEquals) {
if(!(IsEquals == (I0.hashCode() == I1.hashCode())))
throw new AssertionError();
}
public static void main(String ... args) {
testEqualEqual( 1, 1, true);
testEqualEqual(2000, 2000, false);
testEqual( 1, 1, true);
testEqual(2000, 2000, true);
testHash( 1, 1, true);
testHash(2000, 2000, true);
System.out.println("Done");
}
}
To understand this, you should know first that the number number 255 will be cached when autoboxed. This means that Integer of 1 is always the same object but Integer of 2000 will always be different object.
This experiment shows that '==' return true when the objects are the same. In case of '1' they are the same number and it returns true. But in case of '2000' autoboxed to be different objects so it returns false.
The experiment also shows that '==' does not use equals() or hashCode().
Hope this helps.
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 7 years ago.
public class MainClass
{
public static void main(String[] args)
{
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2);
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);
}
}
i1,i2,i3,i4 are not objects I guess they are only reference variables. So how they work differently from class variables?
Answer I heard is
true
false
But how? Why is it different for 127 and 128?
Since Java 5, wrapper class caching was introduced. The following is an examination of the cache created by an inner class, IntegerCache, located in the Integer cache. For example, the following code will create a cache:
Integer myNumber = 10
or
Integer myNumber = Integer.valueOf(10);
256 Integer objects are created in the range of -128 to 127 which are all stored in an Integer array. This caching functionality can be seen by looking at the inner class, IntegerCache, which is found in Integer:
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. Therefore, consider the following example:
Integer i = 100;
Integer p = 100;
if (i == p)
System.out.println("i and p are the same.");
if (i != p)
System.out.println("i and p are different.");
if(i.equals(p))
System.out.println("i and p contain the same value.");
The output is:
i and p are the same.
i and p contain the same value.
It is important to note that object i and p only equate to true because they are the same object, the comparison is not based on the value, it is based on object equality. If Integer i and p are outside the range of -128 or 127 the cache is not used, therefore new objects are created. When doing a comparison for value always use the “.equals” method. It is also important to note that instantiating an Integer does not create this caching.
Remember that “==” is always used for object equality, it has not been overloaded for comparing unboxed values
Also see Integer wrapper objects share the same instances only within the value 127?
Integer is an object and hence the == check if the variables refer to the exact same instance. Equality of objects can be checked using the myObject.equals(otherObject)
int is the primitive type of Integer and in that case the == would return true if both the ints have the same value
update: please note that in some case, as for String for example, two variables can share the same reference depending from the code and the compiler but still it is not something you should base your code logic on.
I know the concept of String pool in PermGen area of heap. So when we do something like
String firstString = "Stack";
String secondString = "Stack";
both references firstString and secondString point to the same object in the pool. But I tried the same for a variable of type int.
int firstInt = 5;
int secondInt = 5;
if(firstInt == secondInt) {
System.out.println("Both point to same allocated memory");
} else {
System.out.println("Both point to different allocated memory");
}
and the result is Both point to same object and when i tried
Integer firstInteger = new Integer(2);
Integer secondInteger = new Integer(2);
if(firstInteger == secondInteger) {
System.out.println("Both point to same object");
} else {
System.out.println("Both point to different object");
}
output is Both point to different object
I tried the same for char and the result is similar. So my question do we have pools for all primitive types like int, char? And when we actually create objects with same content using new () as in the second case mentioned above is the object cloned and stored in same pool area or is it outside the pool?
There is so much misconception in your post, it is hard even to start explaining. Get some decent book. For now, some facts that might help you:
String is not a primitive type,
there are no pools of primitive types, because there cannot be a reference to a primitive type (the answer saying that they are only kept on the stack is plain wrong!)
if you use new, you bypass pools anyway; so executing new String("ala") will always create a new String object; you cannot change the semantics of new;
if you want to use available pools, use factory methods on objects (like Integer.valueOf), they will - to some extent - pool instances (it is not viable or beneficial to pool all possible values of Integers, Floats etc.).
Primitives are not objects. They can be stored directly in the generated code.
In your second code block, you're testing equality of value, not that two objects are the same.
int firstInt = 5;
int secondInt = 5;
if(firstInt == secondInt)
{
System.out.println("Both point to same object");
// NO - neither point to an object -- their alues are the same.
}
You can share the same Integer object among multiple references by explicitly using Integer.valueOf(int), which may return the same object for multiple calls.
If you try
if (Integer.valueOf(2) ==Integer.valueOf(2))
you will get true.
With the Integer firstInt = new Integer(2) you create a new local variable that is != to another local variable created with Integer secondInt = new Integer(2). Same goes for String type.
The reason behind this is that == checks equality of the variables. Variables could be different (== results in false) even though they point to two objects that are "the same". The same in this context means obj1.equals(obj2) returns true.
If you want object representation of primitve types and also StringS to be stored in PermGen then do not use new keyword, i.e. Integer firstInt = 2;, String firstString= "whatevs"; beacause the keyword new creates an object on the heap.
Sometimes, to answer advanced questions it is enough to look through source code. For instance, here is the code of Integer#valueOf(int i) method:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Values IntegerCache#low and IntegerCache#high could be changed via vm options:
The size of the cache may be controlled by the -XX:AutoBoxCacheMax=<size> option.
I believe this is a very valid question that needs to be answered. For any future readers, the way the == operation works for Object types and primitive types are different.
Primitive types(int, char, double, long....) are evaluated by their values.
Whereas Primitive Wrappers (Integer, Double, String ....) are actually objects and not just values.
So when we use Integer class as
Integer number = new Integer(10)
A new Object is created in the memory which is not the case for primitive data types.
The == evaluation checks the memory, as well as the value for the Object types and for primitive types, checks the value only.
Consider two references of type Integer that call the static factory method valueOf as shown below:-
Integer a = Integer.valueOf("10");
Integer b = Integer.valueOf("10");
Considering that Integer is immutable, is it ok to compare a and b using == instead of using equals method. I am guessing that the valueOf method makes sure that only one instance of Integer with the value 10 is created and a reference to this instance is returned for every Integer created with a value 10.
In general, is it ok to compare two references of an immutable class that are created using a call to the same static factory method by using == instead of equals?
Edit:
The Integer class was used just as an example. I am aware thar Intgers upto 127 will return true if they are compared using ==. What i need to know is that when l create my own immutable class, say MyImmutable with a method create() that will ensure that no duplicate MyImmutable objects are created, will it be ok if I compare 2 MyImmutable references created using the create method by using == instead of equals.
No, that's not safe in general. The == operator compares the references, not the values.
Using == happens to work for integers between -128 and 127, but not for other integers. The following code demonstrates that == won't always work:
Integer a = Integer.valueOf(10);
Integer b = Integer.valueOf(10);
System.out.println(a == b);
true
Integer c = Integer.valueOf(1000);
Integer d = Integer.valueOf(1000);
System.out.println(c == d);
false
See it working online: ideone
The explanation for this behaviour lies in the implementation of Integer.valueOf:
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);
}
source
Not also that the standard requires that boxing integers for small inputs (-128 to 127) gives objects with equal references.
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.
However the standard makes no such guarantees for integers outside this range.
In general, is it ok to compare two references of an immutable class that are created using a call to the same static factory method by using == instead of equals?
As shown above, it won't work in general. But if you ensure that two immutable objects with the same value always have the same reference, then yes, it could work. However there are some rules you must follow carefully:
The constructor must not be public.
Every object you create via the static method must be cached.
Every time you are asked to create an object you must first check the cache to see if you have already created an object with the same value.
== and equals() is fundamentally different.
You should read this post for more details:
Difference between Equals/equals and == operator?
It has nothing to do with immutable objects.
If your factory method returns the same object for equal inputs, it's safe to compare them with ==. For example String.intern works this way. Enums are also could be compared with ==. But Integer.valueOf returns the same object only for -128 ... 127 range (in default configuration).
Integer.valueOf(127) == Integer.valueOf(127)
but
Integer.valueOf(128) != Integer.valueOf(128)
Generally speaking you should use equals method to compare any objects. Operator == could be used to improve performance, when there are small number of different values for object. I wouldn't recommend to use this method, unless you are 100% sure in what you are doing.
Immutability and equality do not necessarily have something to do with each other. == compares for reference equality, that means, it compares if both variables point to the very same instance of the object. Equality means that both objects share the same value. Immutability now means that you can not alter an object after its construction.
So, you might have two immutable obejcts, that represents the same value (meaning, they are equals so that a.equals(b) returns true) but that are not the same instance.
I have a little example for you here:
public class MyPoint {
private int x;
private int y;
public MyPoint(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof MyPoint))
return false;
MyPoint p = (MyPoint) obj;
return this.x == p.x && this.y == p.y;
}
/**
* #param args
*/
public static void main(String[] args) {
MyPoint p = new MyPoint(2, 2);
MyPoint q = new MyPoint(2, 2);
MyPoint r = q;
System.out.println(p == q);
System.out.println(p == r);
System.out.println(q == r);
System.out.println(p.equals(q));
System.out.println(p.equals(r));
System.out.println(q.equals(r));
}
}
The output is:
false
false
true
true
true
true
MyPoint is immutable. You can not change its values / its state after is has been initialized. But, as you can see, two objects of myPoint might be equal, but they might not be the same instance.
I think what you have in mind is some kind of flyweight pattern, where only one object exists for every possible state of the object. Flyweight also means commonly that those obejcts are immutable.
They are not the same object, so == will not be true. With objects, be safe and use equals().