views:

678

answers:

13

I am unable to get what are the scenarios where we need an immutable class.
Have you ever faced any such requirement? or can you please give us any real example where we should use this pattern.

+4  A: 

Java is practically one and all references. Sometimes an instance is referenced multiple times. If you change such an instance, it would be reflected into all its references. Sometimes you simply don't want to have this to improve robustness and threadsafety. Then an immutable class is useful so that one is forced to create a new instance and reassign it to the current reference. This way the original instance of the other references remain untouched.

Imagine how Java would look like if String was mutable.

BalusC
Or if `Date` and `Calendar` were mutable. Oh, wait, they are, OH SH
gustafc
@gustafc: Calendar being mutable is OK, considering its job of doing date calculations (could be done by returning copies, but considering how heavyweight a Calendar is, better this way). but Date - yes, that's nasty.
Michael Borgwardt
On some JRE implementations `String` is mutable! (hint: some older JRockit versions). Calling string.trim() resulted in the original string being trimmed
Salandur
@Salandur: Then it's not a "JRE implementation". It's an implementation of something that resembles a JRE, but isn't.
Mark Peters
@Mark Peters: a very true statement
Salandur
+6  A: 

Hashmaps are a classic example. It's imperative that the key to a map be immutable. If the key is not immutable, and you change a value on the key such that hashCode() would result in a new value, the map is now broken (a key is now in the wrong location in the hash table.).

Kirk Woll
I would rather say it is imperative that the key not be changed; there is no official requirement for it to be immutable though.
Péter Török
Not sure what you mean by "official".
Kirk Woll
@Kirk Woll: I think he means, the only real requirement is that the keys SHOULDN'T be changed... not that they CAN'T be changed at all (via immutability). Of course, an easy way to prevent the keys from being changed is to just make them immutable in the first place! :-)
Platinum Azure
E.g. http://download.oracle.com/javase/6/docs/api/java/util/Map.html: "Note: great care must be exercised if mutable objects are used as map keys". That is, mutable objects _can_ be used as keys.
Péter Török
+1 for being the closest to actually answering the question asked.
ILMTitan
+21  A: 

Immutable classes are in general much simpler to design, implement and use correctly. An example is String: the implementation of java.lang.String is significantly simpler than that of std::string in C++, mostly due to its immutability.

One particular area where immutability makes an especially big difference is concurrency: immutable objects can safely be shared among multiple threads, whereas mutable objects must be made thread-safe via careful design and implementation - usually this is far from a trivial task.

Update: Effective Java 2nd Edition tackles this issue in detail - see Item 15: Minimize mutability.

See also these related posts:

Péter Török
+5  A: 

We don't need immutable classes, per se, but they can certainly make some programming tasks easier, especially when multiple threads are involved. You don't have to perform any locking to access an immutable object, and any facts that you've already established about such an object will continue to be true in the future.

Damien_The_Unbeliever
+19  A: 

Effective Java by Joshua Bloch outlines several reasons to write immutable classes:

  • Simplicity - each class is in one state only
  • Thread Safe - because the state cannot be changed, no synchronization is required
  • Writing in an immutable style can lead to more robust code. Image if Strings weren't immutable; Any getter methods that returned a String would require the implementation to create a defensive copy before the String was returned - otherwise a client may accidently or maliciously break that state of the object.

In general it is good practise to make an object immutable unless there are severe performance problems as a result. In such circumstances, mutable builder objects can be used to build immutable objects e.g. StringBuilder

Tarski
+1 for referring to Effective Java.
Péter Török
+3  A: 

There are various reason for immutability:

  • Thread Safety: Immutable objects cannot be changed nor can its internal state change, thus there's no need to synchronise it.
  • It also guarantees that whatever I send through (through a network) has to come in the same state as previously sent. It means that nobody (eavesdropper) can come and add random data in my immutable set.
  • It's also simpler to develop. You guarantee that no subclasses will exist if an object is immutable. E.g. a String class.

So, if you want to send data through a network service, and you want a sense of guarantee that you will have your result exactly the same as what you sent, set it as immutable.

The Elite Gentleman
I don't get the part about sending over the network, nor the part in which you say that an immutable class cannot be extended.
aioobe
@aioobe, sending data over the network, e.g. Web Services, RMI, etc. And for extended, you cannot extend an immutable String class, or an ImmutableSet, ImmutableList, etc.
The Elite Gentleman
Not being able to extend String, ImmutableSet, ImmutableList, etc. is a completely orthogonal issue to immutability. Not all classes flagged `final` in Java are immutable, and not all immutable classes are flagged `final`.
JUST MY correct OPINION
+3  A: 

Let's take an extreme case: integer constants. If I write a statement like "x=x+1" I want to be 100% confidant that the number "1" will not somehow become 2, no matter what happens anywhere else in the program.

Now okay, integer constants are not a class, but the concept is the same. Suppose I write:

String customerId=getCustomerId();
String customerName=getCustomerName(customerId);
String customerBalance=getCustomerBalance(customerid);

Looks simple enough. But if Strings were not immutable, then I would have to consider the possibility that getCustomerName could change customerId, so that when I call getCustomerBalance, I am getting the balance for a different customer. Now you might say, "Why in the world would someone writing a getCustomerName function make it change the id? That would make no sense." But that's exactly where you could get in trouble. The person writing the above code might take it as just obvious that the functions would not change the parameter. Then someone comes along who has to modify another use of that function to handle the case where where a customer has multiple accounts under the same name. And he says, "Oh, here's this handy getCustomer name function that's already looking up the name. I'll just make that automatically change the id to the next account with the same name, and put it in a loop ..." And then your program starts mysteriously not working. Would that be bad coding style? Probably. But it's precisely a problem in cases where the side effect is NOT obvious.

Immutability simply means that a certain class of objects are constants, and we can treat them as constants.

(Of course the user could assign a different "constant object" to a variable. Someone can write String s="hello"; and then later write s="goodbye"; Unless I make the variable final, I can't be sure that it's not being changed within my own block of code. Just like integer constants assure me that "1" is always the same number, but not that "x=1" will never be changed by writing "x=2". But I can be confidant that if I have a handle to an immutable object, that no function I pass it to can change it on me, or that if I make two copies of it, that a change to the variable holding one copy will not change the other. Etc.

Jay
+9  A: 

*The other answers seem to focused on explaining why immutability is good. It is very good and I use it whenever possible. However, that is not your question. I'll take your question point by point to try to make sure you're getting the answers and examples you need .*

I am unable to get what are the scenarios where we need an immutable class.

"Need" is a relative term here. Immutable classes are a design pattern that, like any paradigm/pattern/tool, is there to make constructing software easier. Plenty of code was written before the OO paradigm came along, but count me among the programmers that "need" OO.

Have you ever faced any such requirement?

If you aren't looking at the objects in the problem domain with the right perspective you may not see a requirement for an immutable object.

The thing about OO (and immutable classes) is that you need to have to correct perspective in order to use it effectively. Or else you end up writing "procedural code" objects and "data struct" objects in an object-oriented language.

I often use immutable classes where I think of a given object in my problem domain as a value or fixed instance. This notion is sometimes dependent on perspective or viewpoint, but ideally, it will be easy to switch into the right perspective to identify good candidate objects.

You can get a better sense of where immutable objects are really useful (if not strictly necessary) by making sure you read up on various books/online articles to develop a good sense for how to think about immutable classes. One good article to get you started is:

http://www.ibm.com/developerworks/java/library/j-jtp02183.html

I'll try to give a couple of examples below of how one can see objects in different perspectives (mutable vs immutable) to clarify what I mean by perspective.

... can you please give us any real example where we should use this pattern.

Since you asked for real examples I'll give you some, but first lets start with some classic examples.

Strings and integers and are often thought of as values. Therefore its not surprising to find that String class and the Integer wrapper class (as well as the other wrapper classes) are immutable in Java. A color is usually thought of as a value, thus the immutable Color class.

In contrast, a car is not usually thought of as a value object. Modeling a car usually means a creating a class that has changing state (odometer, speed, fuel level, etc). However, there are some domains where it car may be a value object. For example, a car (or specifically a car model) might be thought of as a value object.

Playing Cards

Ever write a playing card program? I did. I could have represented a playing card as a mutable object with a suit and rank. A draw-poker hand could be 5 fixed instances where replacing the 5th card in my hand would mean mutating the 5th playing card instance into a new card by changing its suit and rank.

However, I tend to think of a playing card as an immutable object that has a fixed unchanging suit and rank once created. My draw poker hand would be 5 instances and replacing a card in my hand would involve discarding one of those instance and adding a new random instance to my hand.

Map Projection

One last example is when I worked on some map code where the map could display itself in various projections. The original code had the map use a fixed mutating projection class. Changing the map projection meant mutating the projection's instance vars (projection type, center point, zoom, etc).

However, I felt the design was simpler if I thought of a projection as an immutable value or fixed instance. Changing the map projection meant having the map reference a different projection instance rather than mutating the map's fixed projection instance. This also made it simpler to capture named projections such as MERCATOR_WORLD_VIEW.

Bert F
+1 for good, concrete examples.
Scott
i got what i ordered ;)
Rakesh Juyal
+2  A: 
JUST MY correct OPINION
+1  A: 

Using the final keyword doesn't necessarily make something immutable:

public class Scratchpad {
    public static void main(String[] args) throws Exception {
        SomeData sd = new SomeData("foo");
        System.out.println(sd.data); //prints "foo"
        voodoo(sd, "data", "bar");
        System.out.println(sd.data); //prints "bar"
    }

    private static void voodoo(Object obj, String fieldName, Object value) throws Exception {
        Field f = SomeData.class.getDeclaredField("data");
        f.setAccessible(true);
        Field modifiers = Field.class.getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        modifiers.setInt(f, f.getModifiers() & ~Modifier.FINAL);
        f.set(obj, "bar");
    }
}

class SomeData {
    final String data;
    SomeData(String data) {
        this.data = data;
    }
}

Just an example to demonstrate that the "final" keyword is there to prevent programmer error, and not much more. Whereas reassigning a value lacking a final keyword can easily happen by accident, going to this length to change a value would have to be done intentionally. It's there for documentation and to prevent programmer error.

Mark Peters
Note that this doesn't directly answer the question in that it wasn't about final; it was about immutable classes. You can have an immutable class without the final keyword using proper access restrictions.
Mark Peters
A: 

Immutable data structures can also help when coding recursive algorithms. For example, say that you're trying to solve a 3SAT problem. One way is to do the following:

  • Pick an unassigned variable.
  • Give it the value of TRUE. Simplify the instance by taking out clauses that are now satisfied, and recur to solve the simpler instance.
  • If the recursion on the TRUE case failed, then assign that variable FALSE instead. Simplify this new instance, and recur to solve it.

If you have a mutable structure to represent the problem, then when you simplify the instance in the TRUE branch, you'll either have to:

  • Keep track of all changes you make, and undo them all once you realize the problem can't be solved. This has large overhead because your recursion can go pretty deep, and it's tricky to code.
  • Make a copy of the instance, and then modify the copy. This will be slow because if your recursion is a few dozen levels deep, you'll have to make many many copies of the instance.

However if you code it in a clever way, you can have an immutable structure, where any operation returns an updated (but still immutable) version of the problem (similar to String.replace - it doesn't replace the string, just gives you a new one). The naive way to implement this is to have the "immutable" structure just copy and make a new one on any modification, reducing it to the 2nd solution when having a mutable one, with all that overhead, but you can do it in a more efficient way.

Claudiu
+1  A: 

One of the reasons for the "need" for immutable classes is the combination of passing everything by reference and having no support for read-only views of an object (i.e. C++'s const).

Consider the simple case of a class having support for the observer pattern:

class Person {
    public string getName() { ... }
    public void registerForNameChange(NameChangedObserver o) { ... }
}

If string were not immutable, it would be impossible for the Person class to implement registerForNameChange() correctly, because someone could write the following, effectively modifying the person's name without triggering any notification.

void foo(Person p) {
    p.getName().prepend("Mr. ");
}

In C++, getName() returning a const std::string& has the effect of returning by reference and preventing access to mutators, meaning immutable classes are not necessary in that context.

André Caron
A: 

They also give us a guarantee. The guarantee of immutability means that we can expand on them and create new patters for efficiency that are otherwise not possible.

http://en.wikipedia.org/wiki/Singleton_pattern

Ryan Hayes