String is an immutable class in Java. An immutable class is simply a class whose instances cannot be modified. Why does the Java programming language choose to make objects of class String immutable?
3 Answers
This issue is strongly connected to the notion of what it means to be an instance of a class. In strict Object-Oriented terms, a class has an associated invariant: a predicate which always holds true on exit from a (public) method of the class. Such a notion is central in ensuring that inheritance is well-defined, for example (it's part of the Liskov Substitution Principle).
One of the most pernicious issues with Java is that it is difficult to prevent client code from breaking class invariants.
For example, consider the following 'ZipCode' class:
class ZipCode {
private String zipCode;
public ZipCode(String value){
if(!isValidZipCode(value))
throw new IllegalArgumentException();
zipCode = value;
assert(invariant());
}
public String get() { return zipCode; }
public boolean invariant() {
return isValidZipCode( zipCode );
}
}
If String were not immutable, it would be possible for a user of ZipCode to call 'get' and change the characters at any subsequent time, thereby breaking the invariant and destroying the conceptual integrity offered by the encapsulation of the ZipCode concept.
Since this kind of integrity is essential to ensuring that large systems are valid, this answer to your question really begs the wider one of:
"Why doesn't Java support an analog of C++ const, or at least offer immutable versions of more of it's library classes?"
- 1,876
- 14
- 15
- 817
- 4
- 10
Things like strings and dates are naturally values. In C++ terms, we expect them to have a copy constructor, an assignment operator, and an equality operator, but we never expect to take their address. Hence, we don't expect them to be individually allocated on the heap. Virtual methods make no sense.
Domain objects are naturally references. C++ ones have no copy constructor, assignment operator, or equality operator (they are equal only if identical). We can take their address and we do expect them to be heap allocated. Methods are generally virtual.
Java has no value classes, only reference ones. Values are faked with immutable objects. This is true for strings, but not, unfortunately, for dates. The mutability of Java dates has caused frequent problems, and is now deprecated. Mutable values can't be used as a basis for a hash, for example.
- 626
- 3
- 7
Java was designed to allow execution of subsections of a program's code in security constrained environments. The way this requirement was implemented was by setting a "SecurityManager" on a thread that is given access to the parameters of certain critical operations (eg opening a file) and asked whether or not the operation should be allowed to go ahead. If Java Strings were mutable, a program could circumvent such restrictions by creating two threads, one which performed an open file operation that would be allowed while the other modified the string it stored the filename in to one that would not be allowed. There is then a possibility that the security manager would read the original string, accept the operation, which would be passed on to the file opening code which would then precede to open the second (not permitted) file. There are two possible ways of preventing this scenario:
- immutable strings
- performing defensive copying of any security critical string prior to checking its acceptability.
The latter possibility would make all such operations run more slowly and would be more likely for the implementation to contain bugs, so using immutable strings was the most sensible decision.
More generally, immutable objects are useful because they allow sharing without needing to make defensive copies (which may be necessary even in non-security-critical code to prevent bugs when the source data changes), so even without this requirement the decision would still be a reasonable one.
- 211
- 2
- 5