Friday, November 2, 2012

Why String is Immutable in Java

An immutable object is an object whose state cannot be modified after it is created. This is in contrast to a mutable object, which can be modified after it is created. In some cases, an object is considered immutable even if some internally used attributes change but the object's state appears to be unchanging from an external point of view. In this article, we look into the String immutability, why it is necessary, what's its use and what is string pool in Java.

Ways to create string
There are two ways to create a String in java.
  • With new operator
  • Using string literal or constant
For example,
String str = new String("Hello Java Latte");
String str = "Hello Java Latte";       (literal)
String str1 = "Hello"+"Java"+"Latte";  (constant exp)

String Literal pool

String allocation, like any other object creation proves costly in time and memory.The JVM do some trickery while instantiating the string literals to increase performance and decrease memory overhead. To decease the number of creation of String object in JVM, the String class keeps a pool of Strings. Each time you create a string literal, the JVM checks the string literal pool first. If a string is found in the pool, a reference to the pooled string is return.if the String is not exist in the pool, a new string object is instantiates, then placed in the pool.

Why String is immutable

1.Imagine String pool facility without making string immutable.It is not possible at all because in case of string pool with one string object/literal
e.g. "Java Latte" has reference by many reference variable, if one them change the value others will be automatically affected i.e. let say
String A="Java Latte"
String B="Java Latte"
Now String B called "JAVA LATTE".toUpperCase() which change into JAVA LATTE, so A will also be changed which is not desirable .

2.Since String is immutable it can be safely shared between multiple threads which is very important in multi threaded application and to avoid any synchronization issue. Also you no need to synchronize String operation externally.


3. String in immutable means, no one can change its contents once created and which guarantee the hashcode of string to be same in multiple invocation. So Java, cache the string hashcode and do not calculate every time we call its hashcode method of string, which make it very fast as hashmap key used in HashMap in java.


4. Most important reason for string to immutable is that it is used by the class loading mechanism and thus have security aspects. Had string been immutable, a request to load jdbc.driver could have been changed to "mysql.driver".

This is the same reason for making String final.

Though final and immutable are 2 different things e.g. StringBuffer is a final class in java but still mutable. But certain feature of String class will not be possible until string is final.

equals()  vs  ==

Equals can be consider to perform a deep comparison of the value of a object. It compare the content of 2 objects rather then references. Whereas == perform a shallow comparison. == operator with reference type evaluate to true if the references are identical means point to the same location.
Example :
String s1="hello"
String s2="hello"
s1==s2 return true
s1.equals(s2) return true

String s3=new String("hello");

String s4=new String("hello");
s3==s4 return false
s3.equals(s4) return true

String s5="he"+"llo";

String s6="h"+"ello";
s5==s6 return true
s5.equals(s6) return true.

The creation of 2 string with the same sequence of letters without the use of new operator will create pointers to the same location in string literal pool. 
The literal pool is a way java conserves resources.

String.intern()

The Java String class has a method called intern(), used to create an internal pool of unique strings. Given a string str, saying:
str = str.intern();
adds the string to the internal pool if not already there, and returns a reference to the interned string. Interned strings can be compared with each other using ==, which is much cheaper than using equals() to do the comparison. String literals are always interned.

When you use
String str=new String("java latte");
a string object is created out of the string literal pool , even if an equals string is already exists in the pool. Avoid new String unless you need it !

A JVM has string literal pool where it keep at most one object of the same type. String literal always refers to an object string literal pool. 
Since the object created with new String do not refer to objects in the String literal pool but you can made them with the help of String's intern() method.

java.lang.String.intern() return interned String i.e, one that has an entry in the global pool. If string is not already there, then it will be added.


Example of intern()

String s1 = "java latte";
String s2 = new StringBuffer("java").append(" latte").toString();
String s3 = s2.intern();

s1==s2 return false

s1==s3 return true;

JVM is maintaining a table containing single reference to each unique string object in the global string pool ever created by an instance in order to optimize space. 
This means, there is always a reference to the String object in the string pool, therefore string object in the string pool is not eligible for garbage collection.



If you know anyone who has started learning Java, why not help them out! Just share this post with them. Thanks for studying today!...

2 comments: