1
class Demo
{  
    public static void main(String[] args)  
    {  
        String s1 = new String("ABC");
        String s2 = s1.concat("ABC");
        String s3 = s2.intern();
        System.out.println(s2 == s3); //true

        String s4 = "ABCABC";
        System.out.println(s3 == s4); //true
    }  
}

String s2 = s1.concat("ABC"); would create a new String object "ABCABC" on the heap area. String s3 = s2.intern(); should create a new String object onto the String constant pool.

Since these are two different objects, their references shouldn't be equal. But seems that i'm missing out on something important related to intern().

jason0x43
  • 3,363
  • 1
  • 16
  • 15

3 Answers3

3

From the docs of intern:

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

Before intern is called, the string ABCABC is actually already in the string pool! And according to the above, if the string is already in the pool, intern just returns the string from the pool, rather creating a duplicated string in the pool. This is the same instance as the string created from a literal in your code.

"Why is the string already in the pool?" I hear you ask. This is because strings are not added to the string pool when they first appear in the source code. The compiler collects all the string literals in the source code, and puts them in the class file. All the strings in the class file are put into the string pool when your program begins running.

To actually see the behaviour that you expect, you must not use the string literal "ABCABC". For example, you can replace it with "ABC".concat("ABC"):

String s4 = "ABC".concat("ABC"); // this creates a new string
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • concat() cannot determine what would the final string look like until execution. String s2 would actually be allocated in the Heap area. Consider this example, class Main { public static void main(String[] args) { String s1 = new String("ABC"); String s2 = s1.concat("ABC"); String s3 = "ABCABC"; System.out.println(s2 == s3); } } If s2 was already in the pool then why does s2 == s3 result in false. – Syed Zabi Ulla Sep 02 '20 at 09:44
  • @ZabiKhan In the example in your comment, `s2` is not already in the string pool, as it is created with `concat`. `s3` is the same string, but it is in the string pool, because it refers to a string literal. The same string (as determined by `equals`) can be in the string pool and outside it at the same time. – Sweeper Sep 02 '20 at 09:47
  • 1
    @ZabiKhan Please don't change your question once answers are posted, as this would invalidate the answers. I have rolled back your edit. – Sweeper Sep 02 '20 at 09:52
  • @ZabiKhan Your edited question would be a duplicate of [this](https://stackoverflow.com/questions/55135968/the-return-of-string-intern-explained). I suggest reading that first. – Sweeper Sep 02 '20 at 09:55
  • the edit was done to make the question more concise. – Syed Zabi Ulla Sep 02 '20 at 10:01
  • Could you please answer by not considering s4 in the snippet. – Syed Zabi Ulla Sep 02 '20 at 10:02
  • 1
    @ZabiKhan So you were asking about why `s2 == s3` is true? Then your question would be closed as a duplicate as I said. – Sweeper Sep 02 '20 at 10:04
  • Thanks a ton for clarifying my doubts. Lastly can i conclude in this example - String s1 = new String("ABC"); String s2 = s1.intern(); Since we have used new String() it would create a new instance for s1 in the heap. But in this example - String s1 = "ABC".concat("ABC"); String s2 = s1.intern(); Because of intern(), the String ABCABC will be moved to constant pool. If intern() would not be applied on this s1, then ABCABC would have remained in the heap. Please acknowledge my understanding. – Syed Zabi Ulla Sep 02 '20 at 10:26
  • 1
    Correction: the time when compile-time constants will be added to the pool, is implementation dependent. In this particular example, when `s2 == s3` is `true`, it’s a proof that `"ABCABC"` was *not* in the pool yet. As otherwise, the result of `s1.concat("ABC")` could not become a pool member. Then, when `String s4 = "ABCABC";` is executed, the constant gets resolved to the same object that has been added with `String s3 = s2.intern();`. So `s3 == s4` is guaranteed to be `true`, but in environments with eager constant resolving `s2 == s3` would be `false`. – Holger Oct 13 '20 at 09:24
  • 1
    And generally “moved to constant pool” and “remained in the heap” are inappropriate phrases. All objects are stored in heap. The runtime string pool is just a table of *references* to some of the strings. Adding a string to the pool means adding a reference. The string object itself stays where it is. – Holger Oct 13 '20 at 09:26
0

From javadoc:

Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String. When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true. All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.

So the internal string pool for your code evolve as follow:

public static void main(String[] args)  
{
    String s1 = new String("ABC");  
    // "ABC" generate a new string and add it to intern pool.
    // new String("ABC") uses the already present ABC string to generate a new copy that is not present in the pool. 
    // s1 points to that string that is not present in the internal pool
   

    String s2 = s1.concat("ABC"); 
    // "ABC" is already present. s1.concat("ABC") creates a new string ABCABC that is added to the internal pool. s2 point to that string   

    String s3 = s2.intern();         
    // s2.intern() returns a pointer to ABCABC that is already present in the internal pool. s3 points to that string


   System.out.println(s2 == s3);
   // Prints true because ABCABC present in the internal pool is pointed by both s2 and s3.

    String s4 = "ABCABC";
    // ABCABC is already present in the internal pool. s4 points to that string

    System.out.println(s3 == s4);  
    // Prints true because all s2, s3, s4 points to the same instance ABCABC present in the internal pool.
}  
Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
-1

In my opinion,The intern method add the string into String constant pool if there is not the string,and then return the String reference.

so, s4="ABCABC" aready has existed the String pool

xzg
  • 181
  • 1
  • 2
  • 8