Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Thinking in Java
Prev Contents / Index Next

The drawback to immutability

Creating an immutable class seems at first to provide an elegant solution. However, whenever you do need a modified object of that new type, you must suffer the overhead of a new object creation, as well as potentially causing more frequent garbage collections. For some classes this is not a problem, but for others (such as the String class) it is prohibitively expensive.

The solution is to create a companion class that can be modified. Then, when you’re doing a lot of modifications, you can switch to using the modifiable companion class and switch back to the immutable class when you’re done.

The preceding example can be modified to show this:

//: appendixa:Immutable2.java
// A companion class to modify immutable objects.
import com.bruceeckel.simpletest.*;

class Mutable {
  private int data;
  public Mutable(int initVal) { data = initVal; }
  public Mutable add(int x) {
    data += x;
    return this;
  }
  public Mutable multiply(int x) {
    data *= x;
    return this;
  }
  public Immutable2 makeImmutable2() {
    return new Immutable2(data);
  }
}

public class Immutable2 {
  private static Test monitor = new Test();
  private int data;
  public Immutable2(int initVal) { data = initVal; }
  public int read() { return data; }
  public boolean nonzero() { return data != 0; }
  public Immutable2 add(int x) {
    return new Immutable2(data + x);
  }
  public Immutable2 multiply(int x) {
    return new Immutable2(data * x);
  }
  public Mutable makeMutable() {
    return new Mutable(data);
  }
  public static Immutable2 modify1(Immutable2 y) {
    Immutable2 val = y.add(12);
    val = val.multiply(3);
    val = val.add(11);
    val = val.multiply(2);
    return val;
  }
  // This produces the same result:
  public static Immutable2 modify2(Immutable2 y) {
    Mutable m = y.makeMutable();
    m.add(12).multiply(3).add(11).multiply(2);
    return m.makeImmutable2();
  }
  public static void main(String[] args) {
    Immutable2 i2 = new Immutable2(47);
    Immutable2 r1 = modify1(i2);
    Immutable2 r2 = modify2(i2);
    System.out.println("i2 = " + i2.read());
    System.out.println("r1 = " + r1.read());
    System.out.println("r2 = " + r2.read());
    monitor.expect(new String[] {
      "i2 = 47",
      "r1 = 376",
      "r2 = 376"
    });
  }
} ///:~


Immutable2 contains methods that, as before, preserve the immutability of the objects by producing new objects whenever a modification is desired. These are the add( ) and multiply( ) methods. The companion class is called Mutable, and it also has add( ) and multiply( ) methods, but these modify the Mutable object rather than making a new one. In addition, Mutable has a method to use its data to produce an Immutable2 object and vice versa.

The two static methods modify1( ) and modify2( ) show two different approaches to producing the same result. In modify1( ), everything is done within the Immutable2 class and you can see that four new Immutable2 objects are created in the process. (And each time val is reassigned, the previous object becomes garbage.)

In the method modify2( ), you can see that the first action is to take the Immutable2 y and produce a Mutable from it. (This is just like calling clone( ) as you saw earlier, but this time a different type of object is created.) Then the Mutable object is used to perform a lot of change operations without requiring the creation of many new objects. Finally, it’s turned back into an Immutable2. Here, two new objects are created (the Mutable and the result Immutable2) instead of four.

This approach makes sense, then, when:

  1. You need immutable objects and
  2. You often need to make a lot of modifications or
  3. Thinking in Java
    Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire