1

In Java when we write

String S1 = "TestString";
String S2 = "TestString";

and then compare with if(S1==S2), we get true as the boolean result. The explanation for the same being that the String constants are created in the String Pool and hence it is the same string constant that is being referred here by both S1 and S2. Also, if we write something like

String S1 = new String("TestString");

String S2 = new String("TestString");

and then do the comparison with if(S1==S2), we get false. The reason being that the references of S1 and S2 are different since the strings literals are created in the heap.

My Question is that where was the String literal "TestString" which was passed in the constructor created? Is it same as a String literal/constant? and hence should be created in the Pool as was in the case 1 ? if it is then when we write something like after the above two statements

String S3 = "TestString";

this should not create a new String literal and comparing if(S1==S3) should give me true but it gives false.

So i am not able to figure out where and when is this string literal passed in the constructor getting created.

Any help would be greatly appreciated. Thanks

Navneet
  • 81
  • 1
  • 8

2 Answers2

4

My Question is that where was the String literal "TestString" which was passed in the constructor created? Is it same as a String literal/constant? and hence should be created in the Pool as was in the case 1 ?

Correct, the constant string passed to the constructor invocation new String("TestString") is stored in the string pool, just like in the statement String S1 = "TestString".

String S1 = new String("TestString");

String S2 = new String("TestString");

String S3 = "TestString";

In this case S1==S3 gives false because S3 refers the string literal that was created by the argument of the constructor used for S1, whereas S1 is a different string (because it is created with the constructor).

M A
  • 71,713
  • 13
  • 134
  • 174
  • If you open your code in a debugger and have a look at `S1.value` and `S2.value` you will see something like `[C@NNN` where NNN is the hashcode of the char array that represents "TestString". These values will be equal for S1 and S2 supporting the statement that S1 and S2 share the same data – David Soroko Jul 16 '15 at 11:24
  • @DavidSoroko, a) that's an implementation detail b) this has changed between versions c) there's an option in openjdk 8 that may make that can cause those change at runtime – the8472 Jul 16 '15 at 12:11
  • Ok, so if both S1 and S3 share the same string literal/constant. In case of `String S1 = new String("TestString");` S1 has the reference i.e. it stores the memory address of the place where the constant "TestString" was actually stored and so does S3 because(as said above they share the same literal). I still have one question though that when we compare S1 and S3 reference wise then why are they not equal(they must be holding the same memory addresses)? – Navneet Jul 16 '15 at 12:22
  • Because we have: `S1 -> value (char[10]@123)` and `S3 -> value (char[10]@123)` - both S1 and S2 refer to the same character array/location in memory. However S1 and S2 themselves occupy different memory locations and consequently`S1 == S2` is false – David Soroko Jul 17 '15 at 14:07
  • @Navneet `S1` does _not_ store a reference to the `String` literal. It stores a reference to a `String` object that _contains_ the literal. On the other hand, `S3` references the literal. Hence `S1 == S3` is false. – M A Jul 17 '15 at 15:04
  • @DavidSoroko : If I am able to interpret your comment correctly then are you implying that whenever we do a reference comparison like `if(S1==S2)` then in such cases instead of the values stored in S1 and S2 getting compared, the memory address of S1 and S2 itself will get compared ? S1 and S2 are both on the stack and they contain the address values of the respective objects which they refer to from the Heap. So S1 and S2 itself will occupy different locations(addresses). Please correct me if I am misinterpreting what you wanted to say. – Navneet Jul 17 '15 at 16:56
  • @manouti : yes, I think that's the point I was missing...one refers to the object and other refers to the literal. Thanks. – Navneet Jul 17 '15 at 16:56
  • Yes, the memory address of S1 and S2 itself will get compared. This is how `==` is defined in Java (for non primitive types) – David Soroko Jul 17 '15 at 17:54
  • Perhaps this will help, in a similar way, if you have `Boolean a = new Boolean(true)` and `Boolean b = new Boolean(true)` it is not true that `a == b` – David Soroko Jul 17 '15 at 18:37
0

if(S1==S2), we get false.

That's is because you have three different Strings, S1, S2 and the string literal. S1 and S2 are copies of the String object and have different references. Thus none of them are == one another.

My Question is that where was the String literal "TestString" which was passed in the constructor created?

It was created on the heap like all other objects (Since Java 6) It was also added to the String intern() pool so any other String literal which as the same would be the same object.

Is it same as a String literal/constant?

All the String literals with the same contents will be the same object.

String S3 = "TestString"; this should not create a new String literal

Correct. The String literal has already been created.

comparing if(S1==S3) should give me true

I have no idea why. S1 is a copy of the string literal, not the string literal itself.

but it gives false.

as expected.

So i am not able to figure out where and when is this string literal passed in the constructor getting created.

Before Java 7, String literals were created when the class was loaded, in Java 7+ it is created when it is first used.

if both S1 and S3 share the same string literal/constant

Up to Java 6, they shared the same underlying char[]. From Java 7, this is not true. The String objects have always been and will always be different.

S1 has the reference i.e. it stores the memory address of the place where the constant "TestString" was actually stored

S1 is a copy so it store a reference of a copy of the string literal.

I still have one question though that when we compare S1 and S3 reference wise then why are they not equal(they must be holding the same memory addresses)

They have different addresses which is why == gives false.

S1 and S2 are both on the stack and they contain the address values of the respective objects which they refer to from the Heap. So S1 and S2 itself will occupy different locations(addresses).

Notionally S1 and S2 have different location and point to different locations. However when the code is turned in machine code to actually run it can be optimised such that variables are in registers, not on the stack and any variable which is not used is discarded. i.e. it could be that no objects ever exist.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130