I had read in some design book that immutable class improves scalability and its good practice to write immutable class wherever possible. But I think so immutable class increase object proliferation. So is it good of going immutable class or better go for static class (A class with all the methods static) for improve scalability ?
The main benefit of immutable classes however is that you can expose internal data members that are immutable because the caller can't modify them. This is a huge problem with, say, java.util.Date
. It's mutable so you can't return it directly from a method. This means you end up doing all sorts of defensive copying. That increases object proliferation.
The other major benefit is that immutable objects do not have synchronization issues, by definition. That's where the scalability issues come in. Writing multithreaded code is hard. Immutable objects are a good way of (mostly) circumventing the problem.
As for "static classes", by your comment I take it to mean classes with factory methods, which is how it's usually described. That's an unrelated pattern. Both mutable and immutable classes can either have public constructors or private constructors with static factory methods. That has no impact on the (im)mutability of the class since a mutable class is one whose state can be changed after creation whereas an immutable class's state cannot be changed after instantiation.
Static factory methods can have other benefits however. The idea is to encapsulate object creation.
As cletus said, immutable classes simplify class design and handling in synchronized methods.
They also simplify handling in collections, even in single-threaded applications. An immutable class will never change, so the key and hashcode won't change, so you won't screw up your collections.
But you should keep in mind the lifecycle of the thing you're modeling and the "weight" of the constructor. If you need to change the thing, immutable objects become more complex to deal with. You have to replace them, rather than modify them. Not terrible, but worth considering. And if the constructor takes nontrivial time, that's a factor too.
Immutability is generally used to achieve scalability, since immutability is one of the enablers when it comes to concurrent programming in java. So while, as you point out, there may be more objects in an "immutable" solution, it may be a necessary step to improve concurrency.
The other, equally important use og immutability is to consume a design intention; whoever made an immutable class intended you to put mutable state elsewhere. If you start mutating instances of that class, you are probably breaking the original intention of the design - and who knows what the consequences may be.
Consider string objects, as an example. Some languages or class libraries provide mutable strings, some don't.
A system that uses immutable strings can do certain optimizations that one with mutable strings cannot. For example, you can ensure that there is only one copy of any unique string. Since the size of the object "overhead" is generally much smaller than the size of any non-trivial string, this is a potentially massive memory savings. There are other potential space savings, like interning substrings.
Besides the potential memory savings, immutable objects can improve scalability by reducing contention. If you have a large number of threads accessing the same data, then immutable objects don't require elaborate synchronization processes for safe access.
Just one more consideration about the subject. Using immutable object allow you to cache them and not re-create them everytime (ie Strings) it helps a lot on your application performance.
One thing to consider: If you intend to use instances of a class as keys in a HashMap, or if you're going to put them in a HashSet, it's safer to make them immutable.
HashMap and HashSet count on the fact that the hash code for an object remains constant as long as the object is in the map or set. If you use an object as a key in a HashMap, or if you put it in a HashSet, and then change the state of the object so that hashCode() would return a different value, then you're confusing the HashMap or HashSet and you'll get strange things; for example, when you iterate the map or set the object is there, but when you try to get it, it's as if it is not there.
This is due to how HashMap and HashSet work internally - they organize objects by hash code.
This article by Java concurrency guru Brian Goetz gives a good overview of the pros and cons of immutable objects.
Immutable classes do promote object proliferation, but if you want safety, mutable objects will promote more object proliferation because you have to return copies rather than the original to prevent the user from changing the object you return.
As for using classes with all static methods, that's not really an option in most cases where immutability could be used. Take this example from an RPG:
public class Weapon
{
final private int attackBonus;
final private int accuracyBonus;
final private int range;
public Weapon(int attackBonus, int accuracyBonus, int range)
{
this.attackBonus = attackBonus;
this.accuracyBonus = accuracyBonus;
this.range = range;
}
public int getAttackBonus() { return this.attackBonus; }
public int getAccuracyBonus() { return this.accuracyBonus; }
public int getRange() { return this.range; }
}
How exactly would you implement this with a class that contains only static methods?
I think, if you want to share the same object among different variables, it needs to be immutable.
For instance:
String A = "abc";
String B = "abc";
String object in Java is immutable. Now both A & B point to the same "abc" string. Now
A = A + "123";
System.out.println(B);
it should output:
abc
Because String is immutable, A will simply point to new "abc123" string object instead of modifying the previous string object.