Yes, String is Immutable. Means once the data is assigned to a String variable, it stores in a memory slot where the data can not be modified. If you try to modify the data, it’ll create a new data slot and the reference variable point to the new dataslot.
String s = "abc"; //This will create a dataslot in string pool of stack memory, and point the reference variable 's' to that data slot. s.concat("def"); System.out.println(s); // Guess the output? It is "abc". [the concated data is stored in a new dataslot, but reference variable 's' is still referencing to the old dataslot] s = s.concat("def"); System.out.println(s); // Now the output is "abcdef". [The concated data is stored in new dataslot and the reference variable 's' is pointing to this new dataslot];
Then, the data present in previous dataslot of string pool won’t be changed, instead a new dataslot will be created in the string pool and the reference variable ‘s’ will point to the new dataslot created.
Then what about the previous dataslot?
Garbage Collector will take care of that. GC will clear the memory slots of all in regular cycles, to those there are no reference variables. So that memory will be cleared.
So with the above example and discussion, we concluded that String is Immutable.
StringBuffer & StringBuilder:
Before discussing about StringBuilder& StringBuffer, first let’s know why these are used when we have ‘String’. The answer is because String is Immutable and these are Mutable versions of String. Means when you have a requirement that you need to add/modify the data multiple times after initial assignment, then use StringBuilder. If you do the same with String, it’ll create a new memory slot for data for each modification which leads to memory leakage/wastage.
StringBuilder & StringBuffer are mutable. Means once the data is stored in a dataslot, if you modify the data, then it won’t create a new dataslot, it just updates the existing dataslot and the reference variable point to the same dataslot.
StringBuffer sb = new StringBuffer("abc"); // mutable, synchronized sb.append("def"); System.out.println(sb); StringBuilder sbuilder = new StringBuilder("abc"); // mutable, non synchronized sbuilder.append("def"); System.out.println(sbuilder);
Note: StringBuilder is introduced in Java 1.5, in Java 1.4 there is only StringBuffer.
Why StringBuilder came when there is StringBuffer?
It’s very rare that you really need to build strings in a thread-safe manner, so why pay the synchronization cost? So that is the reason StringBuffer is obsolete now.