Friday, October 1, 2010

Why String is immutable or final in Java

String is VVS Laxman of Java, i.e. very very special class. I have not seen a single Java program which is written without using String. That's why solid understanding of String is very important for a Java developer. Important and popularity of String as data type, transfer object and mediator has also make it popular on Java interviews. Why String is immutable in Java is one of the most frequently asked String Interview questions in Java, which starts with discussion of,  What is String, How String in Java is different than String in C and C++, and then shifted towards what is immutable object in Java , what are the benefits of immutable object, why do you use them and which scenarios should you use them. This question some time also asked as "Why String is final in Java". e


Why String is Final in Java

As I said, there could be many possible answer of this question, and only designer of String class can answer it with confidence, I think following two reasons make a lot of sense on why String class is made Immutable or final in Java : 1) Imagine String pool facility without making string immutable , its not possible at all because in case of string pool one string object/literal e.g. "Test" has referenced by many reference variables , so if any one of them change the value others will be automatically gets affected i.e. lets say

String A = "Test"
String B = "Test"

Now String B called "Test".toUpperCase() which change the same object into "TEST" , so A will also be "TEST" which is not desirable.

2)String has been widely used as parameter for many Java classes e.g. for opening network connection, you can pass hostname and port number as string , you can pass database URL as string for opening database connection, you can open any file in Java by passing name of file as argument to File I/O classes.

In case, if String is not immutable, this would lead serious security threat , I mean some one can access to any file for which he has authorization, and then can change the file name either deliberately or accidentally and gain access of those file. Because of immutability, you don't need to worry about those kind of threats. This reason also gel with, Why String is final in Java, by making java.lang.String final, Java designer ensured that no one overrides any behavior of String class.

3)Since String is immutable it can safely shared between many threads ,which is very important for multithreaded programming and to avoid any synchronization issues in Java, Immutability also makes String instance thread-safe in Java, means you don't need to synchronize String operation externally. Another important point to note about String is memory leak caused by SubString, which is not a thread related issues but something to be aware of.

4) Another reason of Why String is immutable in Java is to allow String to cache its hashcode , being immutable String in Java caches its hashcode, and do not calculate every time we call hashcode method of String, which makes it very fast as hashmap key to be used in hashmap in Java.  This one is also suggested by  Jaroslav Sedlacek in comments below. In short because String is immutable, no one can change its contents once created which guarantees hashCode of String to be same on multiple invocation.

5) Another good reason of Why String is immutable in Java suggested by Dan Bergh Johnsson on comments is: The absolutely most important reason that String is immutable is that it is used by the class loading mechanism, and thus have profound and fundamental security aspects. Had String been mutable, a request to load "java.io.Writer" could have been changed to load "mil.vogoon.DiskErasingWriter"


Security and String pool being primary reason of making String immutable, I believe there could be some more very convincing reasons as well, Please post those reasons as comments and I will include those on this post. By the way, above reason holds good to answer, another Java interview questions "Why String is final in Java".  Also to be immutable you have to be final, so that your subclass doesn't break immutability.  what do you guys think ?


Few more String related post from Javarevisited, you may like:

56 comments :

Javin @ Tibco RV Tutorial said...

Hi Sandeep,

As per my knowledge ,String pool gets created in PERM area of Java Heap , so if there are too many String there is good chance of OutOfMemoryError because garbage collection doesn't happen in PERM area of java heap.

Thanks
Javin

Javin @ Tibco RV Tutorial said...

Thanks Sandeep , Good to see you here back. Given extensive usage of String in any Java application and immutability benefit it provides as you pointed out which make it preferred choice in case of hashmap key or sharing between multiple thread everybody should know more about String Pool and behavior of String class.this is mine initiative :)

Anonymous said...

Very good. It is the same reason why String is final. If String is not final, you can always extend it so that it is no longer immutable.

Dan Bergh Johnsson said...

The absolutely most important reason that String is immutable is that it is used by the class loading mechanism, and thus have profound and fundamental security aspects.

Had String been mutable, a request to load "java.io.Writer" could have been changed to load "mil.vogoon.DiskErasingWriter".

Javin @ Tibco RV Tutorial said...

@Dan Bergh Johonsson.

You are absolutely right. Since string is used in many place to identify names (whether its class, file , network or anything else) and if you left String immutable you will end of with big security hole.

Thanks John for highlighting some important thing and adding value to this blogpost.

Jaroslav Sedlacek said...

String class is not a common class. It has a specific requirements and it is handled as special by both JVM Specification and Java Language Specification. Many language features depend on ability of String to represent constant text - some of them mentioned above.

One of the "side effect" of String immutability is an ability to cache its hash value which greatly improves String performance in hash based collections.

Javin @ Tibco RV Tutorial said...

Thanks Jaroslav Sedlacek , you really highlighted very good point "ability to cache hash value of String class". I guess that is true for wrapper class also which makes these classes very good candidate for hashMap or hashtable keys.

AhmedOsama said...

Thanks for this amazing info .
That explains why no one uses StringBuffer to hold a connection info of DB.

Javin @ Tibco RV Tutorial said...

Thanks Ahmed , good to know that you find this useful and you brought up a good example also that database connection name is also passes as string and not as mutable stringbuffer.

Javin @ Tibco RV Tutorial said...

Hi Michael,

Thanks you liked the post , yes I gonna compile the ideas/information mentioned in comments in the main article whenever time allows me.

Thanks
Javin

anshuiitk said...

Javin, Good article. Apart from the reason listed above and the pros and cons, the main reason I think why we have immutable claases like Integer String etc is because of space. As a designer you are always fighting for memory and performance, and this is a nice little feature provided by Java to make things efficient and consume less space.

http://anshuiitk.blogspot.com/

javaisfinal said...

you are absolutely correct mate above reason can be used to answer interview question "Why String is final in Java". Though final and immutable are two different thing e.g. StringBuffer is a final class in java but still mutable but Certain feature of String class will not be possible until String are final in Java. I don't say use above reason as it is but they can safely use to answer Why String is final in java.

Anonymous said...

In one of the interview , i was asked, how will you make a class emp immutable , it has some member variable, and another member variable say Salary, on which you don't have any control. In the sense the interviewer said the methods in salary class, can actually change the state of class salary.

Any answers

Anonymous said...

Hashcode could of course be cached even if Strings were mutable, the cached value would just have to be erased whenever the instance was modified. That's certainly doable. Bigger problems with mutable Strings as map keys is the mutability itself - mutable keys generally break contracts of existing Map and Set interfaces.

*~řäđĥïķã~* said...

@Anonymous: to make a class immutable which has member variables of classes which are mutable, you will have to deep clone the mutable objects so that only a copy of the mutable variables are available to any classes which creates an instance of our immutable class. So in your case you will have to write a method to deep clone your Salary class object when giving out to some other class. Read this article: http://www.javaranch.com/journal/2003/04/immutable.htm

Anonymous said...

Another reason for making String as final Class in Java is to enable String to be used as key in HashMap and Hashtable. If String was not final than any one can change value of String and object will not be retrieved from hashmap. I think this is a very convincing reason to make String final in Java, What do you think ?

Mansi said...

I agree final and immutable are almost has same effect. Whether you say String is final in Java or String is immutable in Java , reason will be same.you can't make string immutable until string is final.

Anonymous said...

garbage collection doesn't happen in PERM area of java heap?

Diya said...

Why String Class is Final or Why String Class is Immutable in Java is the same questions asked to me last week.I didn't about your blog post on String immutability or why String is a final class otherwise I would have answered that interview question quite well:)

jfolson said...

Another problem would be breaking the hashcode and comparable contracts. An object's hashcode cannot change. Neither can it's compareTo values relative to other object's.

Chandraprakash Sarathe said...

I would agree to usage of String as hashkey makes it immutable.Security aspect can be broken in multiple ways.I doubt how String helps here.

http://javaved.blogspot.com

Anonymous said...

If anybody has trouble understanding why Strings are immutable in Java (and other languages) it surely means he/she has never coded in Assembly which is really helpful for understanding a bit more about pointers, primitives, the Stack, etc.

Javin @ String split Java said...

@Anonymous, Indeed coding in Assembly is most difficult and some of Java programmer relatively newer is not even coded in C and C++ which makes them to understand recursion, data-structure, pointers concept even more difficult. immutability is relatively easier concept for them :)

Vivekanand said...

I understand your point on why String is immutable and final in Java but my questions is why String is reference type in Java , why not is just a null terminated character array or primitive type in Java like C or C++ ? Also can you please give example of String being immutable I mean what difference it make ?

Anonymous said...

Java strings are immutable due to flawed design. Witness the [lethora of mutable string-like classes since added to Java.

carrion said...

Just a quick note: final and immutable is not the same! Consider a class Foo with a final member bar and no setters for bar. I can still do stuff like this:
b=new Bar(5);
f=new Foo(b);
b.value=4;
The same problem arises when Foo passes bar to another Method outside it's class scope.

narasimha said...

can you please explain more about how string is useful for security reasons and how can we modify the string if it is mutable.

chikky said...

sir,
yes string is immutable.but my question is as follows:
class StringEx
{public static void main(String args[])
{String s1=”hello”;
string s2=”friend”;
s1=s1+s2;
System.out.println(s1);
}
}
sir, the output for the program is hellofriend
then how can we say that string is immutable bcoz as here the string is being retrived by another would you plz explain it as early as possible..

Fabrizio Benigni said...

I don't get the argument suggested by Dan Bergh Johnsson: a request to load "java.io.Writer" is either specified through the string literal (thus fixed at compile time) or through a string reference (thus modifiable regardless of the immutability of the object).

Fabrizio Benigni said...

@chikky,

you are confusing the concept of object immutability with the concept of variable immutability. When you reassign s1 you don't modify the object referenced by s1; instead, you're creating a new string object and assigning it to the variable s1.

Fabrizio Benigni said...

Regarding the concern with class loading and possibly mutable strings, I think you're confusing the reasons behind the effects of making strings immutable with the effects of the implementation choices that were enabled by the decision of making stings immutable: immutable strings allowed optimizations such as the string pool, which would not make any sense had Strings not been immutable, so obviously there wouldn't be any problem with class loading and the like in case strings were mutable, as in that case we wouldn't have string pools and modifying my string object "java.io.Writer" to "gotcha.hahaha" wouldn't have any effect on another "java.io.Writer" object.

Andrew Glassman said...

The interviewer has his facts messed up. As someone pointed out before, the value[] is not copied, it is a reference. So there is NOT a new 1GB string every time you do a substring. On the other hand, if you are doing substring on a 1GB string only to keep a small substring of that, you most definitely would want to create a new String object. Otherwise you have this small string backed by a huge value[].

Javin @ split string in Java said...

not to worry Andrew, I understand :) By the way glad to welcome here and hope to see some interesting comments :)

Javin

Verhás Péter said...

Forget ALL SECURITY REASONS. As regarding security reasoning String IS mutable:

package com.verhas.elrettentopelda;

import java.lang.reflect.Field;

public class Wtf {
public static void main(String[] args) throws Exception {
String alma = "alma";
String korte = "alma";
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set(alma, new char[] { 'k', 'o', 'r', 't', 'e' });
System.out.println(korte);
}
}

Deep Shah said...

Hello Dir,
As u said:
"String A = "Test"
String B = "Test"

Now String B called "Test".toUpperCase() which change the same object into "TEST" , so A will also be "TEST" which is not desirable."

I tried this example but the output of String A does not changed it's till 'Test' instead of 'TEST'

So , can u please give me the example?

Javin Paul @ sort arraylist in Java said...

Hi Deep, when you call TEST.toUpperCase(), original object will not change because String is immutable it can not be changed once created, instead a new String object will be created.

Anonymous said...

Hii Dear,

What @deep tried is true which is i also tried then how come it changes the same object when it is creating a new one. Please Explain

Niraj Singh said...

Main Reason of String being immutable is performance. Before you guys tear my opinion to shreds please read ahead :-).

Strings are backbone of Java or for that matter any other programming language. As we have seen thousand examples in this great blog itself, for example classloaders uses classname to load a class which is a string, usernames, passwords, database connection names etc. all are stored as string.

Now lets assume for a second that String were not immutable what would happen? String references pointing to litrals in constant pool would keep on changing the contents there hence a havoc would occur.

To fix this java designers would have to remove the constant pool all together. Thus we would have to create a new instance of string all the time which would go into the heaps. Tons of string would result in out of memory errors hence impact the performance of all the java applications.

Javin @ ClassLoader in Java said...

Hi Niraj, Good comment. Performance would definitely will be in mind of Java designers, because whole idea of String pool is caching. Immutability, String pool, Security, Performance these all things put together nicely for String being immutable.

Anonymous said...

If this was the answer given in an interview that I was giving, you would not get the job.
It misses the fundamental reason for using an immutable classes, and that is to allow this object to be shared efficiently without fear of having the underlying value change. All of the listed reasons are secondary to this fundamental point, so not to mention it means that you are not seeing cause and effect in the right direction.


If you take the discussion in point (5) for example, it does not make any sense. These classes were built on the assumption that String was safe to share. If they weren't safe, they would never be used in a context that required safety. It's like saying that glue is sticky because if it weren't, my furniture would fall apart.

Anonymous said...

Hi!
Honestly, I take the security argument with caution. Nothing prevents a mutable object holding the immuatable String to change the reference and so refer to another String.
More, without proper security policy, nothing prevents introspection to change an existing String value and mess up the String pool. Take a look at this code:
String titi = "titi";
String titi2 = "titi";
String titi3 = new String(titi);
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char value[] = {'t', 'o', 't', 'o'};
field.set(titi, value);
System.out.println(titi2); // toto
System.out.println(titi3); // titi

You would expect this to fail, because the field is private and final; But this just works. More interesting, explicitly creating a new instance allow you to avoid some of the problems.

Anonymous said...

I am really unable to understand immutable(object is not modifiable) meaning..

Pls... Give me an example of mutable class and its immutability..

Thank you for noticing me.

Anonymous said...

i don't get the concept of security issue.

@Had String been mutable, a request to load "java.io.Writer" could have been changed to load "mil.vogoon.DiskErasingWriter".

if we change it, [creates a new string] won't it pass the new modified string ?

what is a value in string class that they use to access?

best students said...

yes it is a good article of final, could you please explain something about "How final method bonded during compile time and why it is called static binding "

Please ...

Nitin Taur said...

I do not very much agree with point (4) related to hashcode. Can we use an object as key in hashmap whose hashcode can change once stored in hashmap? Basically this will have same issue as with following class used as key in hashmap:

class A
{
private volatile int i = 1;
@Override
public int hashCode()
{
return ++i;
}
}

I think hashcode should never depend on changing state of object.

Anonymous said...

Good post. Only one note: the hashcode caching is not the reason for making String immutable, but visa versa hashcode caching mechanism is used because String is immutable.

ilavarasan rangasamy said...

Java uses the concept of string literal.Suppose if there are 5 reference variables ,all references to one object.if any reference variable changes the value of an object,it will be affected to all the reference variables.That is why string is immutable in java

Constance said...

The two main reasons why strings are immutable in many modern languages, including Java, are security and performance (or, more precisely, chance for optimizations).

The fact that strings are final is to ensure their immutability (by forbidding anyone from extending them and making them mutable again).

Anonymous said...

why do we need stringpool facility in java??

Simerpreet Singh said...

@Annonymous: We use String Pool because it stores only one reference to String literal eg.
String A = "Test"
String B = "Test"
So in String Pool there is only one instance of "Test" and variable A & B are just reference to that string. Now if you create two "Test" String using new operator eg. new String("Test") it will create a new object everytime but in case of string pool there is only one reference.So i hope you understand string pool is saving time on string related memory operations.

vaibhav sharma said...

Good post!
can you give some highlight on String Buffer and String Builder classes as both are providing mutable objects but in what aspect these are different from String class and where should we use them as compare to String class.
Thanks in advance.

Anonymous said...

A String value in Java is immutable but a String variable is not final. The term "final" specifically marks a memory reference (variable) as a constant that cannot change. The value to which a String variable refers in memory can be changed. In other words, the variable can refer to a different value, even though the original value is immutable.

Anonymous said...

Hi,
I executed below lines of code and unable to understand the output can u plz explain.
String str = "test";
String str1 = "test";
System.out.println(str);
System.out.println(str1);
"test".toUpperCase();
System.out.println(str);
System.out.println(str1);

Output Is:
test
test
test
test

According to first point str and str1 should contains "TEST".

vaibhav sharma said...

The output is right and the reason behind this is while writing "test".toUpperCase(); the value of String str become changed in to TEST but JVM didn't found any reference that refers to new value(TEST).So the reference become lost.And while printing it prints the previous value of string.If you want TEST in output then you should write
str="test".toUpperCase();
Now the reference become updated and new value of String str will be print.

Javin Paul said...

@vaibhav, Yes indeed, that's a side effect of making a class Immutable in Java. You need to be careful to store the modified reference otherwise it can really create hard to find bugs in your code.

Anonymous said...

Hi Javin, one more reason for String being immutable could be that String is more like the primitive type but represented as object. Since java uses pass by value it makes sense for passing an immutable object to the methods as parameter so that pass by value behavior is maintained.

Akshat

Post a Comment