Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a Java string really immutable?

We all know that String is immutable in Java, but check the following code:

String s1 = "Hello World";   String s2 = "Hello World";   String s3 = s1.substring(6);   System.out.println(s1); // Hello World   System.out.println(s2); // Hello World   System.out.println(s3); // World    Field field = String.class.getDeclaredField("value");   field.setAccessible(true);   char[] value = (char[])field.get(s1);   value[6] = 'J';   value[7] = 'a';   value[8] = 'v';   value[9] = 'a';   value[10] = '!';    System.out.println(s1); // Hello Java!   System.out.println(s2); // Hello Java!   System.out.println(s3); // World   

Why does this program operate like this? And why is the value of s1 and s2 changed, but not s3?

like image 780
Darshan Patel Avatar asked Jan 06 '14 07:01

Darshan Patel


People also ask

Is string immutable in Java and why?

The String is immutable in Java because of the security, synchronization and concurrency, caching, and class loading. The reason of making string final is to destroy the immutability and to not allow others to extend it. The String objects are cached in the String pool, and it makes the String immutable.

Is string is immutable yes or no?

String is immutable ( once created can not be changed ) object . The object created as a String is stored in the Constant String Pool. Every immutable object in Java is thread safe ,that implies String is also thread safe . String can not be used by two threads simultaneously.

Why we are saying string is immutable?

Being immutable automatically makes the String thread safe since they won't be changed when accessed from multiple threads. Hence immutable objects, in general, can be shared across multiple threads running simultaneously.

Why string is immutable and SCP in Java?

Because String is immutable so the value one string object is holding will never get changed which means its hashcode will also not change which gives String class an opportunity to cache its hashcode during object creation.


1 Answers

String is immutable* but this only means you cannot change it using its public API.

What you are doing here is circumventing the normal API, using reflection. The same way, you can change the values of enums, change the lookup table used in Integer autoboxing etc.

Now, the reason s1 and s2 change value, is that they both refer to the same interned string. The compiler does this (as mentioned by other answers).

The reason s3 does not was actually a bit surprising to me, as I thought it would share the value array (it did in earlier version of Java, before Java 7u6). However, looking at the source code of String, we can see that the value character array for a substring is actually copied (using Arrays.copyOfRange(..)). This is why it goes unchanged.

You can install a SecurityManager, to avoid malicious code to do such things. But keep in mind that some libraries depend on using these kind of reflection tricks (typically ORM tools, AOP libraries etc).

*) I initially wrote that Strings aren't really immutable, just "effective immutable". This might be misleading in the current implementation of String, where the value array is indeed marked private final. It's still worth noting, though, that there is no way to declare an array in Java as immutable, so care must be taken not to expose it outside its class, even with the proper access modifiers.


As this topic seems overwhelmingly popular, here's some suggested further reading: Heinz Kabutz's Reflection Madness talk from JavaZone 2009, which covers a lot of the issues in the OP, along with other reflection... well... madness.

It covers why this is sometimes useful. And why, most of the time, you should avoid it. :-)

like image 57
Harald K Avatar answered Sep 30 '22 03:09

Harald K