1

I know that String is immutable. In the example below a String constant object will be created in String pooled area and s1 will point to the "Hello". Also s2 will make a String constant with the same value "Hello".

But I don't understand why s2 do not point to the first "Hello". From what I understand String "Hello" already exist in the String pooled area and if I create another String with this value, it will point to the existing object rather than create another object. For example s3 points to the same object like s1.

I didn't use new keyword for s2. Why s2 doesn't point to the same object like s1 and s3?

public class DemoApp {

    public static void main(String args[]) {

        String s1 = "Hello";
        String s2 = "Hello friends".substring(0, 5);
        String s3 = "Hello";

        System.out.println(s2);        //Hello
        System.out.println(s1 == s2);  //false
        System.out.println(s1 == s3);  //true
    }
}

The output is:

Hello
false 
true
trincot
  • 317,000
  • 35
  • 244
  • 286

2 Answers2

1

If you look at the implementation of substring method you will see its create a String with the new operator, thus the returned string is not present in the string pool.

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > value.length) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    int subLen = endIndex - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return ((beginIndex == 0) && (endIndex == value.length)) ? this
            : new String(value, beginIndex, subLen);
}

Replace your code

String s2 = "Hello friends".substring(0, 5);

with String s2 = "Hello friends".substring(0, 5).intern();

you will see its returning true.

0

Only string literals (and constants at compile-time) are pooled.

The substring call computes a new String that does not come from the pool. After all, substring doesn't know beforehand whether or not its result is already pooled. Therefore it has to allocate space for a new String, just in case the result isn't already in the pool. Then, if the space for the result is already allocated, it is wasteful to "check" if that result is already pooled. Hence, you get the behavior you see -- the substring result is not pooled, even though it's equal to something else in the pool.

k_ssb
  • 6,024
  • 23
  • 47
  • 1
    It is not just literals that are pooled, any compile-time constant expression of `String` type will be in the pool, e.g. `"" + 0`. – Andy Turner Apr 22 '18 at 14:36