Monday 4 August 2014

Immutable and Mutable Objects

Immutable Objects

Immutable objects are object whose data (state) cannot change after construction. For example the String object and the Integer object.


Why is String and Integer immutable?

Each String and Integer object must be immutable. Consider a collection which contains the following Strings:

String A = "JAVA";
String B = "JAVA";

If String was mutable and String B called "JAVA".toLowerCase(), String A's content would also changes to lower-case

As a String is immutable "A.toLowerCase();" will only effect String A. this is what we would expect. The same goes for Integer.

When an immutable object such as String or Integer is created its hashcode is cached. This is because the state of this object will never change, so we might as well store its hashcode in cache memory as we will not need to calculate it again, This makes it quicker to identify objects within a collection. A good benefit of immutable objects.

Mutable Objects

Mutable objects are objects who data (state) CAN change. This is good as we need objects like this, but we must make sure things are consistent, for example, in terms of concurrency, if the structure of an immutable object is valid, it will always be valid. A mutable object wont always be valid as its state can change, this could cause huge problems.

Joshua Bloch (Author of Effective Java, READ IT) gives this advice:
"Classes should be immutable unless there's a very good reason to make them mutable....If a class cannot be made immutable, limit its mutability as much as possible."


Quick example of Immutable verses Mutable in efficiency

This is pseudo-code so it may not compile.

The following code shows how not to use string concatenation in a loop:

public String concat(String[] stringArray) {
int count = 0;
String retVal = "";
for(String s : stringArray){
   retVal = retVal + s + count;
   count++
}
return retVal;
}
Explanation
What is actually going on here is we are creating a new String object on each iteration of the loop. Because String is immutable it's state cannot be changed, therefour when we do "retVal = retVal + s + count" we are actually throwing away the old retVal String and creating a new one. As I'm sure you can see over a large loop this can be quite costly and is not efficient.

The following code shows how you should accomplish concatenation in a loop:

public String concat(String[] stringArray) {
int count = 0;
StringBuilder sb = new StringBuilder();
for(String s : stringArray){
   sb.append(s);
   sb.append(count);
   s = s + count;
   count++
}
return sb.ToString();
}

Explanation
Here we are using a StringBuilder, which happens to be a mutable object. This means we can change it's state without creating a new instance (nice and cheap :))

Conclusion
In the first example we see that if the loop needs to iterate 20 times we will effectively create and throw away 19 String objects.
In the second example if the loop needs to iterate 20 times we will only ever create 1 String object. A clear winner in efficiency.












No comments:

Post a Comment