32
class strb
{

    static public void main(String...string)
    {
         StringBuilder s1 = new StringBuilder("Test");
         StringBuilder s2 = new StringBuilder("Test");

         System.out.println(s1); // output: Test
         System.out.println(s2); // Test
         System.out.println(s1==s2); // false
         System.out.println(s1.equals(s2)); //Line 1 output: false
         System.out.println(s1.toString()==s2.toString()); //Line 2 output: false
    }

}

Just have a quick question on .equals.

Regardless of the object content, does .equals return true only if both the object references point to the same object ?


EDIT : Now I understand the part about the .equals but why does Line 2 not return true ?

EDIT : I believe == looks at the reference variable's address and so s1 and s2 cannot be equal.correct me if my assumption is not right

Mohammed H
  • 6,880
  • 16
  • 81
  • 127
UnderDog
  • 3,173
  • 10
  • 32
  • 49
  • 1
    See this thread http://stackoverflow.com/questions/11112602/why-does-stringbuffer-stringbuilder-not-override-equals-or-hashcode and http://stackoverflow.com/questions/11007387/what-is-an-efficient-way-to-compare-stringbuilder-objects – krishnakumarp Sep 02 '13 at 04:37

10 Answers10

66

Yes, StringBuilder does not override Object's .equals() function, which means the two object references are not the same and the result is false.

For StringBuilder, you could use s1.toString().equals(s2.toString())

For your edit, you're calling the == operator on two different String objects. The == operator will return false because the objects are different. To compare Strings, you need to use String.equals() or String.equalsIgnoreCase()

It's the same problem you were having earlier

Derrick
  • 3,669
  • 5
  • 35
  • 50
hotforfeature
  • 2,558
  • 1
  • 16
  • 24
  • 1
    do you know why StringBuilder does not override equals() method.It seems strange. – Algorithmist Sep 02 '13 at 04:42
  • 6
    Essentially, if I had to guess, if you have two StringBuilders, you're more likely to test if they're the same StringBuilder that's been building your string rather than two different builders with the same string. I can't think of many cases where two different instantiated StringBuilders would be building the same thing. – hotforfeature Sep 02 '13 at 04:46
  • 1
    Regarding your 1st sentence, I thought "==" tested references, and ".equals()" tested object values? –  May 07 '16 at 21:20
  • I think StringBuilder() cant compare object values just this!! – milad salimi Sep 13 '20 at 10:52
4

The StringBuilder class does not provide an overriden equals() method. As such, when that method is called on an instance of StringBuilder, the Object class implementation of the method is executed, since StringBuilder extends Object.

The source code for that is

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

Which simply compares reference equality.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
3

The default implementation of .equals for the Object class is as you mentioned.

Other classes can override this behavior. StringBuilder is not one of them.

String is one of them, which overrides it to ensure that the String representations of both objects result in the same sequence of characters. String API

Refer to the documentation for the specific object in question.

Derrick
  • 3,669
  • 5
  • 35
  • 50
tschaible
  • 7,635
  • 1
  • 31
  • 34
2

for your first answer check @abmitchell 's Answer

And for your Edit:

In Java, String is an object and we can't compare objects for value equality by using ==

== is used for comparing primitives values or object references.

To compare Object values we use equals() in Java

AbdelRahmane
  • 289
  • 2
  • 12
Tarsem Singh
  • 14,139
  • 7
  • 51
  • 71
2

Check the contract of equals method:

it must be consistent (if the objects are not modified, then it must keep returning the same value).

That's why StringBuilder does not override it regardless of its content.

Let's take example above.

     StringBuilder s1 = new StringBuilder("Test");
     StringBuilder s2 = new StringBuilder("Test");

Maybe, to you it is expected that s1.equals(s2) returns true due to current run time values.

But what about if you change add line:

    s1.append("abc");

Then s1 and s2 will have different string contents and s1.equals(s2) is expected to be false. But it is in contradiction with consistency.

Derrick
  • 3,669
  • 5
  • 35
  • 50
jade
  • 2,059
  • 1
  • 11
  • 2
  • *"Check the contract of equals method"* excellent explanation of why StringBuilder does not implement `.equals()`. Great answer. – Jonathan E. Landrum Oct 29 '19 at 13:27
  • I'm sorry, but this remains a violation of least astonishment. Take your interpretation of the charter: "if the objects are not modified". Well the objects _are_ modified. The goal of the equals() method is an evaluation of the functional equivalence of two objects. "Consistency", by your assessment, would never be violated by any object because no object, mutable or otherwise, would fall into that category. The moment mutation happens to an object (e.g. `.append()`), the contract of the equals() _should always_ reflect a contents change. – alife Jul 15 '21 at 11:15
1

StringBuilder and StringBuffer not override the equals function of Object class.but string override the equals method. the function of Object is this

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

you could write your code like this.

System.out.println(s1.toString() == s2.toString());
System.out.println(s1.toString().equals(s2.toString()));
Derrick
  • 3,669
  • 5
  • 35
  • 50
very9527
  • 891
  • 7
  • 9
1

StringBuilder class doesn't have the implementation of equals() method like one in the String class.

So it executes default Object class functionality, which again checks only for address equivalency, which is not same in this case. so it prints false.

Note 1: You can use == operator on objects also, but it simply checks if the address of both the objects are same or not.

Note 2: == operator plays good role in comparing two String objects created in string constant pool, to find out if it is really creating a new object in string constant pool or not.

Derrick
  • 3,669
  • 5
  • 35
  • 50
user1923551
  • 4,684
  • 35
  • 29
0

Agreed with both of the above responses, but I'm worth noting to actually compare contents you can do:

System.out.println(s1.toString().equals(s2.toString())); //Line 1
Derrick
  • 3,669
  • 5
  • 35
  • 50
pfrank
  • 2,090
  • 1
  • 19
  • 26
0

Since StringBuilder does not have a equals method, it is best to first change the StringBuilder to String and then check equality. Eg - sb1.toString().equals(sb2.toString()).

Note: The == operator or sb1 == sb2 will never work here because the two StringBuilder(s) are completely different objects.

Shadab Hashmi
  • 326
  • 3
  • 10
0

As others have said, StringBuilder does not override equals. However, it does implement Comparable (since Java 11). Therefore, you can check s1.compareTo(s2) == 0 to find out if the string representations are equal.

floxbr
  • 144
  • 1
  • 9