What is mean by Immutable ? Immutable means, once created you can't change its value. In Java String is immutable. Changing the value of String results, creation of new object by JVM. The following are reasons behind the making of String as Immutable.
Concurrency & Multithreading Benefits:
Java is known for Concurrency and Multi – threading since its birth. We know that sharing mutable objects between multiple threads is problematic. One thread can change the properties of shared object behind back of another thread without that thread being aware of it.
There are so many c++ bugs on multithreads because of a shared String – where one module thought it was safe to change when another module in the code had saved point to it and expected it to stay the same.
The solution to this is that every class makes a defensive copy of the mutable objects that are passed to it. For mutable strings, this is O(n) to make the copy. For immutable Strings making copy is O(1) because it isn’t a copy, it’s the same object that can’t change.
In a multithreaded environment, immutable objects can always be safely shared between each other. This leads to an overall reduction in memory usage and improves memory caching, also no external synchronization, means much cleaner code. This single feature makes already complicate, confusing and error prone concurrency coding much easier.
Java has clear goal in terms of providing a secure environment at every level of service and String is critical in those whole security stuff. String has been widely used as parameter for many java classes , e.g for opening network connection, you can pass host and port as String, for reading files , you can pass path of files and directory as String and for opening database connection, you can pass database URL, user name, password as String. Being able to change this at an undetermined time late in the execution can lead to security issues ( the function though it was connecting to one machine, but was diverted to another, but everything in the objet looks like it connected to the first).
As java supports Reflection to create objects, invoke methods dynamically by passing class names, method names as Strings. If the String is mutable, this poses a security issue that one can modify the string through the way to invoke another method, instead of actual method.
Class Loading Mechanism:
Another reason for making String final or Immutable was driven by the fact that it was heavily used in class loading mechanism. If the String is not immutable, a user can take advantage of this fact and request to load malicious classes instead of standard java classes. e.g. instead of java.util.ArrayList, user can request to load com.unknown.Doc . By keeping String final & immutable, one can be sure that JVM is loading correct classes.
Keys to the Hash, & Performance Optimization:
The Hash Table and Hash Map are the most used data structures. The keys to these data structures are very often Strings. The Hash Table does not need to make a copy of Hash Key each time in case of Immutable Strings. If the String is mutable, it would be possible that the Hash Key may change at some other location.
The Immutable classes have performance benefit of caching hash code. In case of String class, it caches its hash code. It even calculates hash code lazily. In simple word, when you make a call to hashCode() of String class, it calculate hash code on the fly, and all subsequent calls to hashCode() returns already calculated, cached value. This results in good performance gain, as Strings are heavily used in Hash Maps. In case of String is mutable, it has to calculate hash code each time.
The Goal behind String pool was to reduce creation of temporary String objects, by sharing an instance of String between multiple String literals which have same value, and in order to share, they must have to be from Immutable class. You can’t share a mutable object with two parties which are unknown to each other. Let's take a hypothetical example, where two reference variables are pointing to same String object:
String s1 = "Java"; String s2 = "Java";
Now if s1 changes the object from "Java" to "Scala", reference variable also got value s2="Scala", which it doesn't even know about it. By making String immutable, this sharing of String literal was possible. In short, key idea of String pool can’t possible to implement without making String final or Immutable in Java.
By having the String be immutable, the underlying character array that backs the data structure is also immutable. This allows for certain optimizations on the substring method of String.
String foo = "smiles"; String bar = foo.substring(1,5);
The value of bar is 'mile'. However, both foo and bar can be backed by the same character array, reducing the instantiation of more character arrays or copying it - just using different start and end points within the string.
Now, the downside (prior to Java 1.7) of that (the memory leak) is that if one had a 1k long string and took the substring of the first and second character, it would also be backed by the 1k long character array. This array would remain in memory even if the original string that had a value of the entire character array was garbage collected.
Note that the way the substring constructor is implemented was changed with Java 1.7.