Is "new String()" immutable as well?
JavaStringImmutabilityJava Problem Overview
I've been studying Java String for a while. The following questions are based on the below posts
http://www.ntu.edu.sg/home/ehchua/programming/java/J3d_String.html">Java String is special
https://stackoverflow.com/questions/1552301/immutability-of-strings-in-java">Immutability of String in java
-
Immutability: Now, going by the immutability, the String class has been designed so that the values in the common pool can be reused in other places/variables. This holds good if the
String
was created asString a = "Hello World!";
However, if I create String likeString b = new String("Hello World!");
why is this immutable as well? (or is it?). Since this has a dedicated heap memory, I should be able to modify this without affecting any other variable. So by design, was there any other reason whyString
as a whole is considered immutable? Or is my above assumption wrong? -
Second thing I wanted to ask was about the common string pool. If I create a string object as
String c = "";
is an empty entry created in the pool?
Is there any post already on these? If so, could someone share the link?
Java Solutions
Solution 1 - Java
new String()
is an expression that produces a String
... and a String
is immutable, no matter how it is produced.
(Asking if new String()
is mutable or not is nonsensical. It is program code, not a value. But I take it that that is not what you really meant.)
> If I create a string object as String c = "";
is an empty entry created in the pool?
Yes; that is, an entry is created for the empty string. There is nothing special about an empty String
.
(To be pedantic, the pool entry for ""
gets created long before your code is executed. In fact, it is created when your code is loaded ... or possibly even earlier than that.)
> So, I was wanted to know whether the new heap object is immutable as well, ...
Yes it is. But the immutability is a fundamental property of String objects. All String
objects.
You see, the String
API simply does not provide any methods for changing a String
. So (apart from some dangerous and foolish1 tricks using reflection), you can't mutate a String
.
> and if so what was the purpose?.
The primary reason that Java String
is designed as an immutable class is simplicity. It makes it easier to write correct programs, and read / reason about other people's code if the core string class provides an immutable interface.
An important second reason is that the immutability of String
has fundamental implications for the Java security model. But I don't think this was a driver in the original language design ... in Java 1.0 and earlier.
> Going by the answer, I gather that other references to the same variable is one of the reasons. Please let me know if I am right in understanding this.
No. It is more fundamental than that. Simply, all String
objects are immutable. There is no complicated special case reasoning required to understand this. It just >>is<<.
For the record, if you want a mutable "string-like" object in Java, you can use StringBuilder
or StringBuffer
. But these are different types to String.
1 - The reason these tricks are (IMO) dangerous and foolish is that they affect the values of strings that are potentially shared by other parts of your application via the string pool. This can cause chaos ... in ways that the next guy maintaining your code has little chance of tracking down.
Solution 2 - Java
String is immutable irrespective of how it is instantiated
- Short answer is yes,
new String()
is immutable too.
Because every possible mutable operation (like replace
,toLowerCase
etcetra) that you perform on String
does not affect the original String
instance and returns you a new instance.
You may check this in Javadoc for String
. Each public
method of String
that is exposed returns a new String
instance and does not alter the present instance on which you called the method.
This is very helpful in Multi-threaded environment as you don't have to think about mutability (someone will change the value) every time you pass or share the String
around. String
can easily be the most used data type, so the designers have blessed us all to not think about mutability everytime and saved us a lot of pain.
Immutability allowed String pool or caching
It is because of immutability property that the internal pool of string was possible, as when same String value is required at some other place then that immutable reference is returned. If String
would have been mutable then it would not have been possible to share String
s like this to save memory.
String immutablity was not because of pooling, but immutability has more benefits attached to it.
String interning or pooling is an example of Flyweight Design pattern
- Yes it will be interned like any other
String
as a blankString
is also as much aString
as otherString
instances.
References:
Solution 3 - Java
The Java libraries are heavily optimized around the constraint that any String
object is immutable, regardless of how that object is constructed. Even if you create your b
using new
, other code that you pass that instance to will treat the value as immutable. This is an example of the Value Object pattern, and all of the advantages (thread-safety, no need to make private copies) apply.
The empty string ""
is a legitimate String
object just like anything else, it just happens to have no internal contents, and since all compile-time constant strings are interned, I'll virtually guarantee that some runtime library has already caused it to be added to the pool.
Solution 4 - Java
-
The immutable part isn't because of the pool; it just makes the pool possible in the first place. Strings are often passed as arguments to other functions or even shared with other threads; Making Strings immutable was a design decision to make reasoning in such situations easier. So yes -
String
s in Java are always immutable, no matter how you create them (note that it's possible to have mutable strings in java - just not with theString
class). -
Yes. Probably. I'm not actually 100% sure, but that should be the case.
Solution 5 - Java
From the Java Oracle documentation:
> Strings are constant; their values cannot be changed after they are > created.
And again:
> String buffers support mutable strings. Because String > objects are immutable they can be shared.
Generally speaking: "all primitive" (or related) object are immutable (please, accept my lack of formalism).
Related post on Stack Overflow:
- https://stackoverflow.com/questions/1552301/immutability-of-strings-in-java
- https://stackoverflow.com/questions/18634966/is-java-string-immutable?lq=1
- https://stackoverflow.com/questions/40480/is-java-pass-by-reference?lq=1
- https://stackoverflow.com/questions/20945049/is-a-java-string-really-immutable?lq=1
- https://stackoverflow.com/questions/8798403/string-is-immutable-what-exactly-is-the-meaning
- https://stackoverflow.com/questions/16828237/what-the-reason-behind-making-string-immutable-in-java?lq=1
About the object pool: object pool is a java optimization which is NOT related to immutable as well.
Solution 6 - Java
This isn't strictly an answer to your question, but if behind your question is a wish to have mutable strings that you can manipulate, you should check out the StringBuilder
class, which implements many of the exact same methods that String
has but also adds methods to change the current contents.
Once you've built your string in such a way that you're content with it, you simply call toString()
on it in order to convert it to an ordinary String
that you can pass to library routines and other functions that only take String
s.
Also, both StringBuilder
and String
implements the CharSequence
interface, so if you want to write functions in your own code that can use both mutable and immutable strings, you can declare them to take any CharSequence
object.
Solution 7 - Java
String is immutable means that you cannot change the object itself no matter how you created it.And as for the second question: yes it will create an entry.
Solution 8 - Java
It's the other way around, actually.
> [...] the String
class has been designed so that the values in the common pool can be reused in other places/variables.
No, the String
class is immutable so that you can safely reference an instance of it, without worrying about it being modified from another part of your program. This is why pooling is possible in the first place.
So, consider this:
// this string literal is interned and referenced by 'a'
String a = "Hello World!";
// creates a new instance by copying characters from 'a'
String b = new String(a);
Now, what happens if you simply create a reference to your newly created b
variable?
// 'c' now points to the same instance as 'b'
String c = b;
Imagine that you pass c
(or, more specifically, the object it is referencing) to a method on a different thread, and continue working with the same instance on your main thread. And now imagine what would happen if strings were mutable.
Why is this the case anyway?
If nothing else, it's because immutable objects make multithreading much simpler, and usually even faster. If you share a mutable object (that would be any stateful object, with mutable private/public fields or properties) between different threads, you need to take special care to ensure synchronized access (mutexes, semaphores). Even with this, you need special care to ensure atomicity in all your operations. Multithreading is hard.
Regarding the performance implications, note that quite often copying the entire string into a new instance, in order to change even a single character, is actually faster than inducing an expensive context switch due to synchronization constructs needed to ensure thread-safe access. And as you've mentioned, immutability also offers interning possibilities, which means it can actually help reduce memory usage.
It's generally a pretty good idea to make as much stuff immutable as your can.
Solution 9 - Java
-
Immutability: String will be immutable if you create it using new or other way for security reasons
-
Yes there will be a empty entry in the string pool.
You can better understand the concept using the code
String s1 = new String("Test");
String s2 = new String("Test");
String s3 = "Test";
String s4 = "Test";
System.out.println(s1==s2);//false
System.out.println(s1==s3);//false
System.out.println(s2==s3);//false
System.out.println(s4==s3);//true
Hope this will help your query. You can always check the source code for String class in case of better understanding Link : <http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java>
Solution 10 - Java
1-String is immutable.See this:
https://stackoverflow.com/questions/20945049/is-a-java-string-really-immutable
So you can create it with many way.
2-Short answer: Yes will be empty.
Solution 11 - Java
Strings created will always be immutable regardless of how they are created.
Answers to your questions:
-
The only difference is:
When string is created like --{String a = "Hello World!";}
then only one object gets created.
And when it is created like --{String b = new String("Hello World!");}
then two objects get created. The first one, because you have used 'new' keyword and the second one because of the String property. -
Yes, for sure. There will be an empty entry created in the pool.
Solution 12 - Java
String is immutable because it does not provide you with a mean to modify it. It is design to avoid any tampering (it is final, the underlying array is not supposed to be touched ...).
Identically, Integer is immutable, because there is no way to modify it.
It does not matter how you create it.
Solution 13 - Java
Immutability is not a feature of new
, it is a feature of the class String
. It has no mutator methods, so it immutable.
Solution 14 - Java
String A = "Test"
String B = "Test"
Now String B called
"Test".toUpperCase()which change the same object into
"TEST", so
Awill also be
"TEST"` which is not desirable.
Solution 15 - Java
Note that in your example, the reference is changed and not the object it refers to, i.e. b
as a reference may be changed and refer to a new object. But that new object is immutable, which means its contents will not be changed "after" calling the constructor.
You can change a string using b=b+"x";
or b=new String(b);
, and the content of variable a
seem to change, but don't confuse immutability of a reference (here variable b
) and the object it is referring to (think of pointers in C). The object that the reference is pointing to will remain unchanged after its creation.
If you need to change a string by changing the contents of the object (instead of changing the reference), you can use StringBuffer
, which is a mutable version of String.