Testing Object Equality
It is a source of great confusion to novice programmers that Java has two ways of thinking about the equality of objects. When used with object references, the == operator returns true only if both references are to the same object. This is illustrated in the following code fragment in which we create and compare some Integer object references:
1. Integer x1 = new Integer( 5 ) ; 2. Integer x2 = x1 ; 3. Integer x3 = new Integer( 5 ) ; 4. if( x1 == x2 ) System.out.println("x1 eq x2" ); 5. if( x2 == x3 ) System.out.println("x2 eq x3" );
Executing this code will print only "x1 eq x2" because both variables refer to the same object. To test for equality of content, you have to use a method that can compare the content of the objects.
The equals Method
In the Java standard library classes, the method that compares content is always named equals and takes an Object reference as input. For example, the equals method of the Integer class (paraphrased from the original for clarity) works like this:
1. public boolean equals(Object obj){ 2. if( obj == null ) return false ; 3. if( !( obj instanceof Integer ) ) return false ; 4. return this.value == ((Integer)obj).intValue() ; 5. }
Note that the equals method does not even look at the value of the other object until it has been determined that the other object reference is not null and that it refers to an Integer object.
The equals method in the Object class (the root of the entire Java hierarchy of classes) returns true only if
this == obj
Therefore, in the absence of an overriding equals method, the == operator and equals methods inherited from Object are equivalent.
CAUTION
Remember that the equals method compares content only if the two objects are of the identical type. For example, an equals test by an Integer object on a Long object always returns false, regardless of the numeric values. Also note that the signature of the equals method expects an Object reference as input. The compiler reports an error if you try to call equals with a primitive value. It is extremely likely that you will get one or more questions involving the equals method.
The == with Strings Trap
One reason that it is easy to fall into the error of using == when you want equals is the behavior of String literals. The compiler optimizes storage of String literals by reusing them. In a large program, this can save a considerable amount of memory. Take the following code fragment:
1. String s1 = "YES" ; 2. String s2 = "YES" ; 3. if( s1 == s2 ) System.out.println("equal"); 4. String s3 = new String( "YES" ); 5. String s4 = new String( "YES" ); 6. if( s3 == s4 ) System.out.println("s3 eq s4");
The String literal "YES" appears in both lines 1 and 2, but the compiler creates only one String object, referred to by both s1 and s2. Thus, line 3 prints out "equal" and it appears to have been tested for equality of content with the == operator. However, the test in line 6 is always false because two distinct objects are involved.
CAUTION
One of the most common mistakes that new programmers make is using the == operator to compare String objects instead of the equals method. At least one question involving understanding the difference is likely to appear on the test.