0

Why methods like concat() returns a new String object instead of returning an object from String pool? I have found that there is a method called intern() which returns the object from String pool. I still don't understand why methods like concat() doesn't use this method when returns a new String.

String a = "test";
String b = "tes".concat("t"); //but not "tes".concat("t").intern();


public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true); // return new String(buf, true).intern();
}
5
  • Because Strings are immutable. See the Javadoc. Commented Mar 12, 2017 at 9:53
  • 1
    Because if all methods started interning all the strings they create, the pool would start consuming a lot of memory, and wouldn't contain frequently used strings, but temporary values that should be garbage-collected as soon as possible. Why d you think the result should be interned? What would be the advantage? And why do you care whether it's interened or not: that shouldn't make any difference. Commented Mar 12, 2017 at 9:54
  • @EJP I know they are immutable. See my new concat method. Commented Mar 12, 2017 at 9:55
  • @JBNizet why the pool would start consuming a lot of memory? I mean all newly created String objects will refer to the object in the constant pool. I think we will use less memory with this way. Commented Mar 12, 2017 at 10:18
  • newly created String objects never reference an object in the pool. new String("foo") is a different object from "foo". Let's say I have System.out.println("tes".concat("t")) in my code, and concat interns the result. I would now have the string "test" in the pool, in addition to "tes" and "t". That consumes memory. But this memory is wasted: I'm done with this string. It has been printed already. And if I execute the same code again, reprinting the same string, it will have to generate a new string and to intern it anyway. Commented Mar 12, 2017 at 10:25

1 Answer 1

3

You should note that calling intern() on a String doesn't prevent the original String being created. i.e. most of the short term cost has been paid and intern()ing it is likely to make matters worse in most use cases.

String.intern() is designed for String constants which are intended to be long lived. They were part of the Perm Gen (until Java 6) and were cleaned up relatively rarely. Another limitation of the String intern pool is that the bucket size didn't resize and you could get a significant hit to performance if you loaded many Strings into it. i.e. it wasn't designed for this.

In the G1 collector you have a -XX:+UseStringDeduplication This reduces String duplication or more specifically the underlying array of the String This doesn't deduplicate the actual String objects as this can have unintended side effects. Note: this deduplication only occurs when the GC runs.

why the pool would start consuming a lot of memory?

The data structure to record the String objects add memory, and is more likely to retain memory as these tend to end up in tenured space and need a major collection to clean out.

I mean all newly created String objects will refer to the object in the constant pool.

You will still create a String which is short lived. And you will use some space in the pool, so for some use cases (in fact most of them) this uses more memory and is harder to clean up.

I think we will use less memory with this way.

It can, which is why the String deduplication is a better option as it will only do the medium to long lived objects.

BTW: Obvious instead of

String b = "tes".concat("t");

you should write

String b = "tes" + "t";

as the javac compiler can combine these.

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

1 Comment

Thanks for the answer. I understand that pool memory is harder to clean up and it uses more memory. But now I am much more confused with your last sentence. Why should I write "test" + "t" instead of concat() method then? Doesn't it creates a new object in pool?

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.