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.
Related
This question already has answers here:
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Closed 7 years ago.
I am not exactly sure why the hashCode() method is returning the same value. Can someone provide more detailed explanation of this?
Source code (Java):
public class Equality {
public static void main(String [] args)
{
String str = "String";
String strOne = new String("String");
System.out.println(str == strOne);
System.out.println(str.equals(strOne));
System.out.println(str.hashCode());
System.out.println(strOne.hashCode());
}
}
From the Javadoc :
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently
return the same integer, provided no information used in equals
comparisons on the object is modified. This integer need not remain
consistent from one execution of an application to another execution
of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must
produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method
on each of the two objects must produce distinct integer results.
However, the programmer should be aware that producing distinct
integer results for unequal objects may improve the performance of
hash tables.
Basically, a.equals(b) => a.hashCode() == b.hashCode() so two identical strings will surely have the same hashCode.
It seems to me that the behaviour you were expecting is the one of ==, but it clearly is not. == is the strongest equality in Java, because it compares the location in memory of two objects. equals comes just after it, it is a logical equality, two objects can be equal even if they have different memory locations. The hashCode has the weakest properties, quoted above.
This should help your understanding. According to the Java 7 docs for String.hashCode() (I believe Java 6/8 should be similar or identical):
public int hashCode()
Returns a hash code for this string. The hash code for a String object is computed as
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
using int arithmetic, where s[i] is the ith character of the string, n is the length of the string, and ^ indicates exponentiation. (The hash value of the empty string is zero.)
The hasCode() method applied on the value of String which is "String" both case.
Although you have created two reference of String type like this -
String str = "String";
String strOne = new String("String");
But the hashCode() use the value assigned with the reference (str and strONe). Thats why the two hashCode() are equals.
Look at the hashCode() method of String class -
public int hashCode() {
int h = hash;
int len = count;
if (h == 0 && len > 0) {
int off = offset;
char val[] = value;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
and value is declared like this -
private final char value[];
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 ==.
I have written following code
class Test {
public static void main(String... args) throws Exception{
Set<Integer> s = new HashSet();
Integer i1 = new Integer(1);
s.add(i1);
Integer i2 = new Integer(2);
s.add(i2);
i1 = 5;
s.remove(i1);
System.out.println("size= "+s.size());
}
}
Output: 2
I have added two integers(i1 and i2) in set and i1 is modified.
When s.remove(i1) is there, output is 2
when I comment out s.remove(i1) still output is 2.
Why this is so.How it is working in background.
Thnaks in advance!
Integer objects are immutable objects and hence any change to them will create a new object. So when you change
i1 = 5;
the original i1 which was stored in set is not changed. As i1 now holds the reference of a different object, which is not present in Set so calling
s.remove(i1);
will have no effect i.e. it does not remove anything and the size of the set remains 2. To confirm whether remove has removed anything or not, you can use boolean return value of remove method. It will return true if the value is removed. So try this:
if(s.remove(i1)) {
System.out.println("i1 removed");
} else {
System.out.println("i1 NOT removed");
}
This line
i1 = 5;
is actually compiled to
i1 = Integer.valueOf(5);
So after execution, i1 is holding another (new) reference, with a value that is not in the HashSet, so nothing is removed.
Java primitives types can only have VALUES.
While Java boxed types have VALUE and IDENTITY.
Two Java boxed types can have same VALUE but different IDENTITY.
Java boxed types are IMMUTABLE; any change in their VALUE will also change the IDENTITY.
If IDENTITY of an object is changed; Java collections cant work effectively.
Statement: i1 = 5; => is actually i1 = Integer.ValueOf(5) => which meant new VALUE of i1.
Collections store only IDENTITY but not VALUE.
Removal by non existing IDENTITY (i1 = 5) from collection, will result nothing.
Source ..... Effective Java by Joshua Bloch
Collections (Set is a collection) in java works with the 'equals()' method, not with the '=' reference operator. That is, when you set 'i1=5', and then 's.remove(i1)', the remove method will compare with all elements.
a) Beginning with the first: is 5 equal to 1?. No, so don't remove that element.
b) The second: is 5 equal to 2?. No, so don't remove that element.
Adding duplicate works the same, on an empty set:
i1=1;
i2=1;
s.add(i1);
s.add(i2)
This will result on a set with only 1 element, because 'i1.equals(i2)' is true, and doesn't matter that 'i1=i2' is NOT true.
It is very important to distinguish between objects and reference variables. A reference expression, including a reference variable, is either null or a pointer to some object.
The HashSet contains its own pointers to the objects in the set it represents. Working through the code:
Set<Integer> s = new HashSet();
// s is a pointer to a new, empty, HashSet.
Integer i1 = new Integer(1);
// i2 is a pointer to an Integer object with value 1
s.add(i1);
// The set contains one Integer object, value 1
Integer i2 = new Integer(2);
s.add(i2);
// The set contains two Integer objects, values 1 and 2
i1 = 5;
// i1 is a pointer to an Integer object with value 5
s.remove(i1);
// The set does not contain any object that is equal
// to an Integer with value 5 so it is unchanged
Becase after you do "i1 = 5;", i1 starts pointing to another address. And it is no more the same Integer than is stored in your HashSet.
This question already has answers here:
How can I properly compare two Integers in Java?
(10 answers)
Closed 5 years ago.
I have the following code:
public class Test {
public static void main(String[] args) {
Integer alpha = new Integer(1);
Integer foo = new Integer(1);
if(alpha == foo) {
System.out.println("1. true");
}
if(alpha.equals(foo)) {
System.out.println("2. true");
}
}
}
The output is as follows:
2. true
However changing the type of an Integer object to int will produce a different output, for example:
public class Test {
public static void main(String[] args) {
Integer alpha = new Integer(1);
int foo = 1;
if(alpha == foo) {
System.out.println("1. true");
}
if(alpha.equals(foo)) {
System.out.println("2. true");
}
}
}
The new output:
1. true
2. true
How can this be so? Why doesn't the first example code output 1. true?
For reference types, == checks whether the references are equal, i.e. whether they point to the same object.
For primitive types, == checks whether the values are equal.
java.lang.Integer is a reference type. int is a primitive type.
Edit: If one operand is of primitive type, and the other of a reference type that unboxes to a suitable primitive type, == will compare values, not references.
Integer objects are objects. This sounds logical, but is the answer to the question. Objects are made in Java using the new keyword, and then stored in the memory. When comparing, you compare the memory locations of the objects, not the value/properties of the objects.
Using the .equals() method, you actually compare the values/properties of objects, not their location in memory:
new Integer(1) == new Integer(1) returns false, while new Integer(1).equals(new Integer(1)) returns true.
ints are a primitive type of java. When you create an int, all that is referenced is the value. When you compare any primitive type in Java, all that is compared is the value, not the memory location. That is why 5 == 5 always returns true.
When you compare an Integer object to a primitive type, the object is cast to the primitive type, if possible. With an Integer and an int this is possible, so they are compared. That is why Integer(1).equals(1) returns true.
What you'll use new Integer(1) to create new object, it creates a totally different object each time even though it has the same value. The '==' checks if the objects are same, not data values. In your case, you could have checked the value as follows :
if(alpha.intValue() == foo.intValue()) {
//
}
Integer == int here auto boxing applied ( so Integer converted to int before comparision) so true.. but Integer == Integer here object comparison so as reference are different so false..
First example:
Using the == operator between objects checks for reference equality, and since you are comparing two different objects they do not equal.
Second example:
When using the == between a wrapper type (Integer, Long, etc.) and a numeric type (int, long, etc.) the wrapper type is unboxed and the equality check is done between the two primitive numeric types (I.e. between int and int). The unboxing is part of binary numeric promotion, read more here: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
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().