Reference Comparison and Content Comparison in Java

607 views Asked by At

I was learning about Reference (or Address) comparison and Content comparison. The below statement makes me confused:

If a class does not override the equals method, then by default, it uses the equals(Object o) method of the closest parent class that has overridden this method.

Point to note: I haven't overridden the .equals() method and I'm only practicing it in my main class.

Below is my code:

package com.reference.content.comparison;

public class ReferenceAndContentComparison {

    public static void main(String[] args) {

        /* "==" operator is used for REFERENCE (or address) comparison. It means, it check if both objects point to same memory location or not.
         * ".equals()" method is used for CONTENT comparison (in String class). It means, it check if both objects have same value or not.
         * 
         * MAIN DIFFERENCES ARE:
         * 1. "==" is an operator while ".equals()" is a method (of Object class).
         * 2. Line 7 to 8.
         * 3. ".equals()" method of Object class is used for REFERENCE comparison but in String class, it is used for CONTENT reference (by overriding .equals()).
         * 4. If a class does not override the equals method, then by default, it uses the equals(Object o) method of the closest parent class that has overridden this method.
         * 5. When comparing two Strings using .equals() method, their content is compared, and not their references.
         *    Link for point 5: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#equals-java.lang.Object-
         */
        String s1 = "HELLO";
        String s2 = "HELLO"; // references s1
        String s3 =  new String("HELLO"); // new instance but same content
 
        System.out.println(s1 == s2); // true; Both s1 and s2 refer to same objects. Their addresses are same.
        System.out.println(s1 == s3); // false; Addresses of s1 and s3 are different.
        System.out.println(s1.equals(s2)); // true; Content of both s1 and s2 are same. Content Reference, because s1 and s2 are string class objects.
        System.out.println(s1.equals(s3)); // true; Content of both s1 and s3 are same. Content Reference, because s1 and s3 are string class objects.
        
        System.out.println("-----");
        
        Thread t1 = new Thread();
        Thread t2 = new Thread();
        Thread t3 = t1;
        String st1 = new String("WORLD");
        String st2 = new String("WORLD");
 
        System.out.println(t1 == t3); // true; Both t1 and t3 refer to same objects. Address of t1 is assigned to t3.
        System.out.println(t1 == t2); //false; Addresses of t1 and t2 are different.
        System.out.println(st1 == st2); // false; Addresses of st1 and st2 are different.
        System.out.println(t1.equals(t2)); /* false; Here, t1 and t2 are both Thread class objects (not String class objects) and we haven't overridden the
                                            .equals() method for Thread class anywhere so by default (as per point 4), .equals() of Object class will be
                                            in effect and hence as per point 3, .equals() will be used as REFERNCE Comparison.
                                            And since addresses are different, it's false.*/
        System.out.println(st1.equals(st2)); /* true; Unlike above scenario, st1 and st2 are String class objects and hence as per point 5, content reference is
                                                happening here and since their contents are same, it is true.*/

    }

}

My confusion is that this t1.equals(t2) gives false because of which reason? Is it because the contents are not matching or reference comparison is happening here? I'm sure that the answer is Reference Comparison since I haven't overridden the .equals() method in my main class and by default it is using the method of the Object class (as stated in the statement at the very beginning).

But consider the below scenario too:

st1.equals(st2) is giving true because of which reason? Contents are matching? Is it not like reference comparison is happening here as well? Or, since contents are matching, it is not a reference comparison but a content comparison? Or, something else? Please explain.

1

There are 1 answers

4
Akash Das On

The String class overrides the equals method that is inherited from the Object class and implemented logic to compare the two String objects character by character.

Why you might ask, did the String class override the equals method inherited from the Object class? Because the equals method inherited from Object performs reference equality!

That's why when comparing two Strings using .equals() method, their content is compared, and not their references.

The evidence is provided by your code itself.

Here are two more pieces of evidence the String overrides the Object.equals(Object)

The Javadoc implies so. Notice that equality is based on the contents of the string. Indeed, even the existence of a distinct Javadoc for the String.equals(Object) method implies that the method has been overloaded ... given the way that javadocs are generated.

The source code says so. Clearly, the linked code is an overload. And clearly, it is not simply comparing object references.

Note

As commented, not all Strings in Java are interned. Try reading something from a file or console, those Strings aren't "interned", thus equals() (and also hashcode()) needs to be overridden.