Friday, October 10, 2008

Why String is Immutable

immutable
Not changeable. All Java variables are by default mutable. You can make them immutable by using the final keyword. You can also make them private and provide no accessors to the outside world to change them. The wrapper classes, Byte, Character, Short, Integer, Long, Float and Double are all immutable. Strings are immutable. StringBuffers are mutable. The only way to change the value of the number inside the object wrapper is to create a new object and point to that instead.
Advantages of Immutablitiy

* You can share immutable objects between threads without danger of changes confusing the other thread. You don’t need any locking. Two threads can both work on an immutable object at the same time without any possibility of conflict.
* Once you check the value, you know it has to stay safe. No one can pass you a value, then behind your back swap it to an unsafe one using a background thread. This is particularly important in high security situations where allowing an invalid value to sneak in could compromise system integrity, e.g. a filename. This is probably the main reason that Strings are immutable.
* You can share duplicates by pointing them to a single instance. You need only one copy, e.g. String interning. This saves RAM. With mutable StringBuilders that were temporarily identical, you could not throw one away, and replace it with a reference to the other, since at any moment their values could diverge again.
* You can create substrings without copying. You just create a pointer into an existing base String guaranteed never to change. Immutability is the secret behind Java’s very fast substring implementation.
* Immutable objects are much better suited to be Hashtable keys. If you change the value of an object that is used as a hash table key without removing it and re-adding it you lose the mapping.
* Since String is immutable, inside each String is a char[] exactly the correct length. Unlike a StringBuilder there is no need for padding to allow for growth.

Returning an Immutable Result
Let us say you wanted to return some data from your method, but you did not want the user to muck with the original. Here are four approaches to the problem:

1. Wrap the reference in an immutable wrapper class and return that.
2. Give the caller his own private copy of the data he can muck with to his heart’s content. There is high CPU and RAM overhead in the array copying.
3. Beg or threaten the user not to modify the data in the reference you return to him.
4. Return an immutable interface to the original data. You can then change fields in the object, but the caller cannot unless he cheats by casting. You expose only the methods you want the user to have. Doing the same with classes is trickier since a subclass must expose everything its superclass does.
5. You can turn a Collection into an immutable Collection with methods like Collections.unmodifiableCollection, Collections.unmodifiableList, Collections.unmodifiableMap, Collections.unmodifiableSet, Collections.unmodifiableSortedMap or Collections.unmodifiableSortedSet.
6. You can return an Iterator with a dummy remove method.

Of course same techniques can be used if you want to pass an Object to a method and you don’t want the method messing with it. You declare the method with an interface parameter and pass it an interface referenece or a reference to an object of some class implementing that interface.

No comments: