An immutable object is one whose state cannot be changed after construction. All the beauty in these objects is that they are simple and safe. In multi-threaded applications all concurrency issues boil down to coordinating access to mutable state. The less mutable state, the easier it is to ensure thread safety. That’s why you should always consider making your objects immutable whenever it is feasible. Creating an immutable type is not a complex process, but you should follow a handful of rules to stay away from pitfalls it definitely implies.
First and topmost, as the object is intended to be unchangeable after construction, it must have all fields as finals and not contain any write methods (this includes property set methods as well as other methods that alter the state of the instance).
This may seem to be sufficient to create a true immutable object, but it is no way to be so. As you should remember variables store not objects themselves but just references to them. Therefore declaring fields as finals just “freezes” only references, but not the referenced objects’ state. So, if another part of the code possesses the same reference as we have, this state can easily be changed from outside forcing our cared object to mute.
To avoid this kind of threat never share references to the stored objects with the outer world. Instead defensively copy them and give away (as well as consume) references to the copied objects.
Here’s how an effective immutable type looks like:
package com.sysgears.examples;
import java.awt.*;
public class Line {
private final Point start;
private final Point end;
public Line(final Point start, final Point end) {
this.start = new Point(start);
this.end = new Point(end);
}
public void draw() {
//...
}
public Point getStart() {
return new Point(start);
}
public Point getEnd() {
return new Point(end);
}
}
Code language: PHP (php)