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.
Security:
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.
String Pool:
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.
Substrings:
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.