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.