7

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.

4
  • 1
    @assylias: yes, it will, since append() returns this. Commented Apr 3, 2013 at 12:44
  • The OP is clear about why the two objects are equal. The question is why the string "I don't get it." will be in string pool. Commented Apr 3, 2013 at 12:47
  • 2
    Its possible you misunderstood your instructor, but if by inserted into the "String pool" he as implying the StringBuffers value would be interned, that is definitely incorrect. Commented Apr 3, 2013 at 12:52
  • possible duplicate of When does StringBuffer adds strings to the String Pool? Commented Apr 3, 2013 at 13:00

6 Answers 6

5

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.

Sign up to request clarification or add additional context in comments.

10 Comments

Ok, it has nothing to do with the string interning.. but is it true that the string "I don't get it" will get in there?
No, the string " I don't get it" won't be interned. Just read the toString() implementation of StringBuffer, and it'll confirm it.
@JBNizet Who's talking about interning the " I don't get it." here? Of course it wouldn't!
I don't see any other way to put a string in the string pool. Do you see one?
@JBNizet I think there is some confusion regarding the"there" in the "will get in there": I mean the StringBuffer, not the interning pool.
|
2

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

1 Comment

Nice example! I think it's easier to see here
0

StringBuffer#append(StringBuffer sb)

Appends the specified StringBuffer to this sequence. The characters of the StringBuffer argument are appended, in order, to the contents of this StringBuffer, increasing the length of this StringBuffer by the length of the argument. If sb is null, then the four characters "null" are appended to this StringBuffer.

Let n be the length of the old character sequence, the one contained in the StringBuffer just prior to execution of the append method. Then the character at index k in the new character sequence is equal to the character at index k in the old character sequence, if k is less than n; otherwise, it is equal to the character at index k-n in the argument sb.

This method synchronizes on this (the destination) object but does not synchronize on the source (sb).

You will get true because the reference is same for both.

Comments

0

There seems to be some confusion. StringBuffer is mutable, which means its contents can be modified. The method append(), from StringBuffer, appends a String to the string inside the buffer and returns the instance. So the line:

StringBuffer str3 = str2.append(" get it.");

Will have the same pratical result as:

str2.append(" get it.");
StringBuffer str3 = str2;

In other words, str3 and str2 point to the same object. Because you appended the String literal " get it." to " I don't", this StringBuffer will contain " I don't get it.".

Comments

0

Why does the string "I don't get it." get in the string pool when the str3 assignement occurs?

It doesn't. Your lecturer is mistaken on this point. The only way that could happen is if StringBuffer calls String.intern(), which it doesn't, or at least isn't specified to do..

Comments

0

You're comparing StringBuffer objects, not (interned) String's. If you take a look at the StringBuffer.append( String ) implementation you will note that it ends with return this;, thus your str2 and str3 is the same object.

public synchronized StringBuffer append(String str) {
super.append(str);
    return this;
}

Edit: While the two string literals in your code are interned (in the "String pool"), the combined string "I don't get it" won't be interned. This is clear by inspecting the StringBuffer code (which represents the combination as a char[] array internally.)

Cheers,

2 Comments

Thank you, but as I mentioned, I think that I get why they refer to the same objects. but can you tell me why the string will be inserted into the "String pool" now?
The string literals "I don't" and " get it" will be interned, the combination of the two won't! Internally StringBuffer uses a char array and only creates a new String(...) when necessary, this does not entail interning.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.