It make sense to make class String
objects immutable with following declarations, because they share the same storage in common pool.
String str1 = "abc";
String str2 = "abc";
But, am not sure, if it make sense to have class String
objects immutable with following explicit constructor declarations, because they do not share the same storage in heap.
String str3 = new String("def");
String str4 = new String("def");
So, if the content of a class String
object has to be modified frequently, it is recommended to learn class StringBuffer
and class StringBuilder
.
Does it make sense to know, What is the reason that class String
has been designed to maintain immutable content with an explicit constructor?
3
Of course it makes sense.
When you get the value you should not care how it was constructed.
It would make no sense if immutability would be dependent of the way an object was constructed:
"abc"
immutable, new String("def")
mutable. It would create a mess.
1
Java strings have to be immutable because Java’s security model depends on the value of them not changing between them being inspected by a SecurityManager instance and consumed by whatever part of the runtime is being protected by the SecurityManager.
For example, if you have a SecurityManager on your thread and you execute:
String str = new String ("innocent.txt");
new FileReader(str);
what happens is that the filename is checked by calling the security manager’s canRead method, and only if that allows the access is the file opened.
But if we could start another thread that could modify the string to a value that wouldn’t be allowed by the security manager between the call to canRead and the file being opened, we could subvert the security and preform operations we’re not supposed to be allowed to do.
An alternative solution would be to make defensive copies of any security-critical string, but this would (1) be error-prone and (2) make the runtime less efficient.
4
Immutability for strings has a lot of advantages even with an explicit constructor (I am sure you know them already: cheap copies, no side-effects, value semantics). The explicit constructor is exactly what everyone expects to be available, without it we would always have to write something ugly like
String s = (new StringBuilder("abc").toString());
The only caveat, where the classic value semantics fails, is the point you asked for: with
String str3 = new String("def");
String str4 = new String("def");
the equality test str3==str4
will fail (one has to use equal
instead), something one would expect to work for classic value semantics.
So the design flaw here is neither the immutability nor the fact there is an explicit constructor for strings, but only the fact the creators of Java did not design the language in a way ==
works as expected. But that is a minor price to pay for not having every string constructed by the tedious string builder line above.
The constructor public String(String original)
is a copy constructor. Its sole purpose is to make a copy of a String object.
Since String is immutable, making copies is rarely needed. That has been covered in the Javadoc of that constructor. However, since String is a core class and it is used everywhere, there could be some special cases requiring copying a String.
The String class has plenty of constructors which are rarely needed in most applications. Actually, using any String constructor to create a new String object is not a common way to get hold of a String in most applications.
They are immutable so they behave like values. You can pass reference to the string and don’t have to fear that whatever code you passed it to might change it.
The explicit constructor is a so-called copy constructor. It’s intended for the rare case where you need to make sure that you receive a new String instance instead of a pooled one. The newly created string still is immutable, as you can’t modify the passed in string reference.