Possibly this is a duplicate, but couldn't find the explanation I needed. Can someone explain me this.
If I'm correct:
String s1 = "a";
String s2 = "a";
Both s1 and s2 will point to the same address in String pool and there will be only one object with value "a".
Now, if I do this:
String s1 = "a"; //line A
s1 = s1.concat("b"); //line B; I don't understand what's happening here in terms of references
String s2 = "ab";//line C
System.out.println(s1 == s2); //false
Why do I get false
?
My way of seeing this (probably wrong), goes like this:
after line A
-> object is created (with value a
) in String pool, referenced by s1
;
after line B
-> object with value b
is created in String pool (with no reference), then new object with value ab
is created in String pool (referenced by existing s1
)
after line C
-> (this is probably I'm wrong) Since existing object with value ab
(referenced by s1
) is created using concat()
(or +), JVM will not reuse this object to be pointed by reference s2
, it will rather just create new object in String pool with value ab
pointed by reference s2
;
Where am I wrong?
TL;DR - the point of your confusion is the Java memory model for Strings, namely the Heap and String Constant Pool areas of the memory.
Design Motivation
In Java, String is probably the most heavily used object. Because of this, Java maintains String objects with a special memory design strategy, holding them either in the Heap, in the isolated subset of the heap called String Constant Pool, or in both.
String Constant Pool is a special space in the Heap memory, which holds String objects of the unique "literal value"
s. Anytime you create a String with its literal value, JVM first checks if the object of the same value is available in the String pool, and if it is, reference to the same object is returned, if it doesn't - the new object is allocated in the String Constant Pool, and the same happens for all other String literal creations again and again.
Reason, why having the Constant Pool is a good idea, is the semantics of this phrase itself - because it stores the constant and immutable String objects, and as you see, this is a great idea for the occasions when you might be creating many String objects with the same literal content - in all those cases, only one object for one "literal value"
will be referenced each time and no newer objects will be created for the existing String literal object.
Note, that this is only possible because, String is immutable by definition. Also, note, that a pool of strings, which initially is empty, is maintained privately by the class String.
Where does Java place String objects?
Now this is where things get interesting. Important point to bear in mind, is that whenever you create String object with a new String()
instruction, you force Java to allocate the new object into Heap; however, if you create a String object with the "string literal"
, it gets allocated in String Constant Pool. As we've said, the String Constant Pool exists mainly to reduce memory usage and improve the re-use of existing String objects in the memory.
So, if you'll write:
String s1 = "a";
String s2 = "a";
String s3 = new String("a");
s1
;"a"
) found in the pool, reference to the same object will be returned;s3
.Internig Strings
If you wish to move the String object, created with new
operator, into the String Constant Pool, you can invoke "your_string_text".intern();
method, and one of two will happen:
String s1 = "a";
String s2 = "a";
Both s1 and s2 will point to the same address in String pool and there will be only one object with value "a".
True. Initially, String object will be created and it will be placed into String Constant Pool. After that, as there is already String with value "a"
, no new object will be created for s2
and reference stored in s1
will be similarly stored into s2
.
Now, let's finally have a look at your question:
String s1 = "a"; //allocated in the String Constant Pool
s1 = s1.concat("b"); //contact() returns a new String object, allocated in the Heap
String s2 = "ab";//"ab" still does NOT exist in the String Constant Pool, and it gets allocated there
System.out.println(s1 == s2); //returns false, because one object is in the Heap, and another is in the String Constant Pool, and as there already exists the object in the pool, with the same value, existing object will be returned by `intern()`.
If you will, however, execute
System.out.println(s1.intern() == s2);
this will return true
, and I hope, by now, you understand - why. Because intern()
will move the object referenced via s1
from Heap to the String Constant Pool.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With