4
String s1 = "Hello".concat("World");
String s3 = new String("HelloWorld"); //Line-2
String s2 = s1.intern();
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //false
System.out.println(s2 == s3); //false

If I removed Line-2 and compare s1==s2, it will return true. Could anyone explain me what exactly happens in string pool after Line-2? And whats happening in each line in heap and in constant pool ?

From what i understand s1 will create "HelloWorld" in constant pool. But still s1 == s2 is false ?

  • Compare Strings with equals method... – zlakad Jan 07 '18 at 17:07
  • 2
    @zlakad i am trying to understand how things are working internally ? – vijay joshi Jan 07 '18 at 17:09
  • 1
    Which Java version are you running the code with? – Mick Mnemonic Jan 07 '18 at 17:11
  • @MickMnemonic Its java 8 – vijay joshi Jan 07 '18 at 17:11
  • What do you mean? You can for example write `String s1 = "a"` and `String s2 = "a"`, and `s1==s2` may and may not be true. – zlakad Jan 07 '18 at 17:14
  • 1
    @zlakad: What Vijay's having trouble with is that after `String s2 = s1.intern()`, when "Line-2" is present in the code, `s1 == s2` is false. But when "Line-2" *isn't* present in the code, `s1 == s2` is true. He's trying to understand why the presence of "Line-2" causes that change. – T.J. Crowder Jan 07 '18 at 17:23
  • *"From what i understand s1 will create "HelloWorld" in constant pool."* How can someone think that? You clearly see the String literal on line too, so how can you think that won't already create the String in the pool and instead it waits for your `intern` call? – Tom Jan 07 '18 at 17:24
  • 1
    @T.J.Crowder, ouch - I was too fast in my comment... – zlakad Jan 07 '18 at 17:33

1 Answers1

10

When you have this:

String s1 = "Hello".concat("World");
String s2 = s1.intern();
System.out.println(s1 == s2); //true

...s1.intern() adds s1 to the pool and returns s1, because there's no equivalent string already in the pool. So naturally s1 == s2 is true.

But when you have this:

String s1 = "Hello".concat("World");
String s3 = new String("HelloWorld"); //Line-2
String s2 = s1.intern();
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //false
System.out.println(s2 == s3); //false

...there's already a "HelloWorld" string in the pool before that code runs (because string literals are put in the pool during class loading). So calling s1.intern() returns the string from the pool, not s1. So s1 == s2 is false.

This is more obvious if we do this:

String s1 = "Hello".concat("World");
String sx = "HelloWorld";
String s3 = new String(sx);
String s2 = s1.intern();
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //false
System.out.println(s2 == s3); //false
System.out.println(s1 == sx); //false
System.out.println(s2 == sx); //true

sx is the one in the pool before the code starts running.

From what i understand s1 will create "HelloWorld" in constant pool

No, concat doesn't put its return string in the pool. s1 is only put in the pool later, when you call s1.intern(), and only if there isn't already an equivalent string in the pool. There isn't when you don't have "Line-2" in the code, but there is when "Line-2" is in the code: The "HelloWorld" literal on that line.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @vijayjoshi: Yeah, sorry, I'd missed the point. Fixed. – T.J. Crowder Jan 07 '18 at 17:15
  • Thanks @T.J. that explains lot, few doubts though. So you mean s1.intern() actually puts "HelloWorld" in String pool incase line2 is commented. In that case shouldn't s1.intern() use the same reference created by line 2 when its not commented ? – vijay joshi Jan 07 '18 at 17:34
  • Actually here i m trying to understand this statement: "So s1.intern returns a different string (the older one already in the pool)" – vijay joshi Jan 07 '18 at 17:35
  • 2
    @vijayjoshi: `intern` doesn't necessarily return the string object you call it on. In fact, that's part of the purpose of `intern`. If you call `intern` on a string object that has the same characters as a different string object already in the pool, `intern` returns the object from the pool instead. But if you call `intern` on a string object that *doesn't* have the same characters as any object already in the pool, `intern` adds it to the pool and returns that same object. In your example, with "Line-2" commented out, `s1.intern()` adds it... *(cont'd)* – T.J. Crowder Jan 07 '18 at 17:38
  • 1
    *(continuing)* ...(there's no `"HelloWorld"` already in the pool) and returns `s1`. But with "Line-2" present, there's *already* a `"HelloWorld"` in the pool (not the same one that `s1` refers to). So `s1.intern()` returns that object, not `s1`. That's what you can see in my final example at the end: `sx` is in the pool before any of that code runs, because literals are interned when the class is loaded. So `s1.intern()` returns `sx`, not `s1`. – T.J. Crowder Jan 07 '18 at 17:39
  • 1
    (Obviously in the above I'm saying things like `s1` instead of "the object that `s1` refers to" for simplicity. :-) ) – T.J. Crowder Jan 07 '18 at 17:42
  • 1
    Thanks @T.J.Crowder fro explaining it nicely !! :) – vijay joshi Jan 07 '18 at 18:00
  • @T.J.Crowder Although it might be different from the topic, but can you please explain why its false for this "System.out.println(s1 == sx); //false" Since when this line will be executed by that time s1.intern() will be executed and s1 should refer to the same "HelloWorld" of sx in String Pool right ? – vijay joshi Jan 07 '18 at 18:05
  • 1
    @vijayjoshi: No, because we never reassign `s1`. We just set `s2` to the result of `s1.intern()`, we didn't *also* update `s1`. So in the case where we have a different string already in the pool, the string object `s1` refers to isn't put in the pool. Calling `intern` has no effect on the string object you call it on (other than *possibly* adding that object to the pool). – T.J. Crowder Jan 07 '18 at 18:07
  • @T.J.Crowder Correct me if i'm wrong, so that means string object s1 is referring to will contain "HelloWorld" string (which is not referenced to the one present in String pool). Does that mean that object will be present in heap ? – vijay joshi Jan 07 '18 at 18:14
  • 1
    @vijayjoshi: Yes. (So are the strings in the string pool.) – T.J. Crowder Jan 07 '18 at 18:23