tags:

views:

249

answers:

10

I've the following test program. I create 3 Integer references. I create 2 Integer objects and make references i1 and i2 refer them respectively. I make reference i3 equal to i1. Now i1 equals() i3 should be obviously true as they both refer to same object on heap. But why should i1 be equal() to i2 ? They are refering to two different objects. What am I missing.

The documentation says:

public boolean equals(Object obj)
     Indicates whether some other object is "equal to" this one.


public class Test{

    public static void main(String [] args)
    {
        Integer i1 = new Integer(10);
        Integer i2 = new Integer(10);
        Integer i3 = i1;

        if(i1.equals(i3)) // UNDERSTANDABLE
            System.out.println("equal");

        if(i1.equals(i2)) // prints equal. WHY !!!!!
            System.out.println("equal");    
}

}
+11  A: 

The equals() methods for the wrapper types test for value equality, if you want to test reference equality, use == instead, e.g.

System.out.println(new Integer(1) == new Integer(1));
Fabian Steeg
+3  A: 

The equals method of the Integer class compares the int values that Integer wraps. As 10 is equal to 10, i1 and i2 are considered equal.

redbrick
+5  A: 

equals is the value version of equality. Classes override this method to define what value equality means. For example, to see if two strings contain the same sequence of characters, you use the .equals() method. If creating your own class, and, for example, you want to add it to a HashMap, you would have to define both a hashCode() and an equals() method for it to work properly.

To see if two references point to the same memory location, use ==.

Claudiu
Using == with autoboxed values gets even more subtle- if two Integer objects have the same value and are within the range -128 <= x <= 127, they will refer to the same object. Check this out: http://bexhuff.com/2006/11/java-1-5-autoboxing-wackyness
JohnE
heh, awesome. this is why primitive types are a fail.
Claudiu
+4  A: 

Because i1 and i2 have the same value. Integer.equals() is implemented like this:

  public boolean equals(Object obj) {
    return (obj instanceof Integer 
            && intValue() == ((Integer) obj).intValue());
  }

So i1 and i2 are Integers and they have the same value, so it will return true.

Drewen
+2  A: 

This is the implementation of equals() in Integer:

public boolean equals(Object obj) {
if (obj instanceof Integer) {
    return value == ((Integer)obj).intValue();
}
return false;
}

with that in mind, if the value of i1 is 10, and the value of i2 is also 10, then 10 == 10 would return true.

akf
+3  A: 

By looking at the Integer class you may get a better idea why. Here is the code is below

/**
 * Compares this object to the specified object.  The result is
 * <code>true</code> if and only if the argument is not
 * <code>null</code> and is an <code>Integer</code> object that
 * contains the same <code>int</code> value as this object.
 *
 * @param   obj   the object to compare with.
 * @return  <code>true</code> if the objects are the same;
 *          <code>false</code> otherwise.
 */
public boolean equals(Object obj) {
if (obj instanceof Integer) {
    return value == ((Integer)obj).intValue();
}
return false;
MKam
+2  A: 

If you read further in the JavaDoc, it provides more details, specifically:

Indicates whether some other object is "equal to" this one. The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

Specifically, it is up to the implementor of "equals(Object)" to decide if two objects are "equal." For reference comparison, us the == operator as others have pointed out.

I also encourage you to read Effective Java if you're interested in this (and other similar) topics.

Jack Leow
+1  A: 

The answer to your question has been already said but I have one note. Be careful because your own objects are extended from Object and there is method equal() implemented like operator == so if you want to compare values you have to override it.

Gaim
A: 

Also note that "Using new Integer(int) is guaranteed to always result in a new object, whereas Integer.valueOf(int) allows caching of values to be done by the compiler, class library, or JVM. Using of cached values avoids object allocation and the code will be faster." --FindBugs

Compare these statements:

System.out.println("new == " + (new Integer(1) == new Integer(1)));
System.out.println("new equals() " + new Integer(1).equals(new Integer(1)));
System.out.println("valueOf() == "
    + (Integer.valueOf(1) == Integer.valueOf(1)));
System.out.println("valueOf() equals() "
    + Integer.valueOf(1).equals(Integer.valueOf(1)));

which produce this output:

new == false
new equals() true
valueOf() == true
valueOf() equals() true
trashgod
+2  A: 

They have same value, that's why it is true. Generally equals method does not test if the references are equal although that is the default behavior.

fastcodejava