Immutable objects in java

Immutable objects in java is the instances whose state once constructed cannot be modified. Now, what do I mean by state. We know that a class contain instance fields as well as methods. So, state of the class is defined by its instance fields. These fields can either be primitive type or some other object and even these fields can be of mutable type. So, what our job as to create immutable class which can have mutable reference but once constructed they could not be modified.

Instances of immutable class are thread safe by design.

There are some general rules that can be followed for creating immutable class.

  1. Do not provide setter methods in the class.
  2. Make the fields of the class as private and final.
  3. Do not allow subclass to override methods. Simplest way to do is to declare a class as final.
  4. If instance field include references to mutable object. Do not allow those objects to be changed.
  • Don't provide methods that modify the mutable objects.
  • Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

Now an example immutable class is as follows.

final public class ImmutableRGB {

    // Values must be between 0 and 255.
    final private int red;
    final private int green;
    final private int blue;
    final private String name;

    private void check(int red,
                       int green,
                       int blue) {
        if (red < 0 || red > 255
            || green < 0 || green > 255
            || blue < 0 || blue > 255) {
            throw new IllegalArgumentException();
        }
    }

    public ImmutableRGB(int red,
                        int green,
                        int blue,
                        String name) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.name = name;
    }


    public int getRGB() {
        return ((red << 16) | (green << 8) | blue);
    }

    public String getName() {
        return name;
    }

    public ImmutableRGB invert() {
        return new ImmutableRGB(255 - red,
                       255 - green,
                       255 - blue,
                       "Inverse of " + name);
    }
}

Look at the invert method and see we are returning the new object instead of modifying existing one.