Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StringBuffer and String pool

Tags:

java

Given the following code:

StringBuffer str2 = new StringBuffer(" I don't");
    StringBuffer str3 = str2.append(" get it.");
    if (str2 == str3)
    {
        System.out.println("Equal");
    }

My lecturer says , that in this case both str2 and str3 will refer to the same object and the string "I don't get it" will be inserted into the "String pool".

I think that I get why str2 and str3 will now refer to the same object, but Why does the string "I don't get it." get in the string pool when the str3 assignment occurs?

For instance, if I do :

 String s = "abcd";

then I know that now the string "abcd" will be inserted into the "String pool" IF its not already there.

I would love to get an explanation.

like image 744
Rouki Avatar asked Apr 03 '13 12:04

Rouki


2 Answers

Why does the string "I don't get it." get in the string pool.

The "I don't get it." string does not get into the interning pool.

One way to verify it is as follows:

StringBuffer str2 = new StringBuffer(" I don't");
StringBuffer str3 = str2.append(" get it.");
String str = new String(str3.toString());
if (str == str.intern()) {
    System.out.println("It was not interned before"); // <<== This is printed
} else {
    System.out.println("It was interned before");
}

If String's content is interned, the call of intern() will return a different ("canonical") object. As you can see, the above returns the same object, meaning that the object on which you call intern() just became the "canonical" one (i.e. has been interned).

On the other hand, if you remove the append, you'd get a different result:

StringBuffer str2 = new StringBuffer(" I don't");
StringBuffer str3 = str2;
String str = new String(str3.toString());
if (str == str.intern()) {
    System.out.println("It was not interned before"); // <<== This is printed
} else {
    System.out.println("It was interned before");
}

Now the string inside str3 is " I don't". Its copy is already interned, because it's the same as the string constant used in creation of the str2.

You can run the first and the second programs side by side to see the difference for yourself.

The reason why str2 == str3 is true has nothing to do with string pools (the slang word is "string interning"). The two are equal because StringBuffer.append returns the object on which the append is invoked, i.e. str2. You do not have a second object - there's only one StringBuffer with two references to it. The content of that StringBuffer is the concatenation of the " I don't" and " get it." strings.

like image 107
Sergey Kalinichenko Avatar answered Oct 20 '22 19:10

Sergey Kalinichenko


What you are missing is the concept of string literal.

The string in added to pool when:

  • It is defined as literal.
  • You invoke method intern on it.

and is not already in the pool.

In your example you put string literals into object of type StringBuffer. To retrieve the string from that object you must call toString(). To add the result to the string pool you must additionally call intern() on that string.

To prove that we can perform a simple test.

String s1 = "This is a simple test";
String s2 = "This is a simple test";

System.out.println(s1 == s2);

StringBuffer sb1 = new StringBuffer(s1);
StringBuffer sb2 = new StringBuffer(s2);

String result1 = sb1.toString();
String result2 = sb2.toString();

System.out.println(result1 == result2);

String internedResult1 = result1.intern();
String internedResult2 = result2.intern();

System.out.println(internedResult1 == internedResult2);

The code output will be:

true
false
true

like image 35
Damian Leszczyński - Vash Avatar answered Oct 20 '22 20:10

Damian Leszczyński - Vash