8
$\begingroup$

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?

$\endgroup$
  • 2
    $\begingroup$ @PJTraill It doesn't seem inevitable at all. String literals in other languages aren't immutable in, say, C, and objects of other classes in Java aren't immutable. $\endgroup$ – David Richerby Dec 10 '15 at 8:29
  • 2
    $\begingroup$ This is a question about programming language design. It seems on-topic, to me. $\endgroup$ – David Richerby Dec 10 '15 at 8:29
  • 2
    $\begingroup$ @DavidRicherby, String literals are immutable in C (In C90 terms: If the program attempts to modify a string literal of either form, the behavior is undefined. Some early version accepted it due to the lack of const in the language, and it did sometimes what the programmer expected, but I don't think it was ever supported) I think everybody has learned from the mistake in early FORTRAN which allowed to change literals. Having literals creating mutable new object whose initial value is the same as the literal on the other hand if not something unsound. $\endgroup$ – AProgrammer Dec 10 '15 at 9:05
  • 1
    $\begingroup$ @AProgrammer Plenty has been written about why Java was designed the way it was: I'd be surprised if there's nothing authoritative about the design decisions around the String class. But, even if the language designers never said why String is immutable, that doesn't make the question off-topic or even bad: it just means that, unfortunately, the only proper answer is "We don't know." $\endgroup$ – David Richerby Dec 10 '15 at 9:17
  • 1
    $\begingroup$ @DavidRicherby It would be better if the question was language-agnostic, though. This one can be answered by citing a statement of a Java dev; we want answers that explain concepts. $\endgroup$ – Raphael Dec 10 '15 at 9:26
8
$\begingroup$

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?"

$\endgroup$
7
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ Well, mutable values can be used for hashing, but you better not mutate them afterwards if you relied on the hash code! $\endgroup$ – gnasher729 Jul 17 '16 at 12:07
6
$\begingroup$

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.

$\endgroup$
  • 1
    $\begingroup$ I'm glad someone pointed this out, because James Gosling was completely clear about this design decision. Java was designed so that you could run untrusted code sent to you over a network (e.g. in a web browser or digital set top box). The primary reason for making strings immutable was to make it easy for vendors or site managers (and the Java standard library implementors!) to implement their own custom security policies. Immutable strings effectively close off one potential attack vector by design. $\endgroup$ – Pseudonym Jul 18 '16 at 1:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.