Java .equals between String and StringBuilder

Solution 1:

Because they both are Different objects.

String object!= StringBuilder object.

But,Your doubt is

name1.equals(s)  returning true

Because in String class equals method ovverided in such a way.

And to get the desired output convert your StringBuilder to String.

System.out.println(s.equals(sb.toString())); //return true.

If you see the Source code of String#equals()

1012    public boolean  equals(Object anObject) {
1013        if (this == anObject) {
1014            return true;
1015        }
1016        if (anObject instanceof String) {             //key line 
1017            String anotherString = (String)anObject;
1018            int n = count;
1019            if (n == anotherString.count) {
1020                char v1[] = value;
1021                char v2[] = anotherString.value;
1022                int i = offset;
1023                int j = anotherString.offset;
1024                while (n-- != 0) {
1025                    if (v1[i++] != v2[j++])
1026                        return false;
1027                }
1028                return true;
1029            }
1030        }
1031        return false;
1032    }

The line if (anObject instanceof String) { always returns false incase if you pass StringBuilder.

Solution 2:

The reason for the two false cases is that this is how the respective equals(Object) methods are specified to work.

  • For String.equals(Object), the javadoc says this:

    "Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object."

  • For StringBuilder.equals(Object), the equals method is inherited from Object, where the javadoc says this:

    "returns true if this object is the same as the obj argument; false otherwise."

So on Line #1 and Line #3, String.equals(Object) returns false because sb is not a String.

And if you reversed it and called sb.equals(name1) or sb.equals(s) you would get false also ... because sb.equals(...) is testing for the same object.


I dont understand why compiler does not think "name1" and "sb" as containing the same value

As you can see, it is nothing to do with the compiler ... and everything to do with the way that the equals method is specified.

Solution 3:

String.equals compares not contents but objects

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        ...
    }
    return false;
}

StringBuilder does not override equals at all and inherits Object.equals

public boolean equals(Object obj) {
    return (this == obj);
}

Solution 4:

Use sb.toString() instead of direct sb directly.

This compares this string to the specified object.

        System.out.println(name1.equals(sb.toString())); //Line 1
        System.out.println(name1.equals(s));  //Line 2
        System.out.println(s.equals(sb.toString()));     // Line 3
        System.out.println(s.equals(name1));  //Line 4

This returns true value for all the line.

true
true
true
true

Solution 5:

Question Issue on Comparing String and Object value Java has been duplicated to this question so posting the answer here

Since String , StringBuffer and StringBuilder are implementing CharSequence you can check the content's equality by using contentEquals method in String

    "java".contentEquals(new StringBuffer("java")); // true
    "java".contentEquals(new StringBuilder("java")); // true