Item 15 - Minimize mutability
From Effective Java 2/e by Joshua Bloch
Immutable Class?
An immutable class is simply a class whose instances cannot be modified
Immutable class examples
- String
- Boxed primitive classes
- BigInteger and BigDecimal
Advantage of immutable classes
- Easier to design, implement, and use
- Less prone to error and are more secure
Rules to follow to make immutable classes
- Don’t provide any methods that modify the object’s state
- Ensure that the class can’t be extended
- Make all fields final
- Make all fields private
- Ensure exclusive access to any mutable components
public final class Complex {
private final double re;
private final double im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
// Static factories instead of constructors
// private Complex(double re, double im) {
// this.re = re;
// this.im = im;
// }
//
// public static Complex valueOf(double re, double im) {
// return new Complex(re, im);
// }
// Accessors with no corresponding mutators
public double realPart() { return re; }
public double imaginaryPart() { return im; }
public Complex add(Complex c) {
return new Complex(re + c.re, im + c.im);
}
public Complex subtract(Complex c) {
return new Complex(re - c.re, im - c.im);
}
public Complex multiply(Complex c) {
return new Complex(re * c.re - im * c.im, re * c.im + im * c.re);
}
public Complex divide(Complex c) {
double tmp = c.re * c.re + c.im * c.im;
return new Complex((re * c.re + im * c.im) / tmp, (im * c.re - re * c.im) / tmp);
}
@Override public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Complex))
return false;
Complex c = (Complex) o;
// See page 43 to find out why we use compare instead of == return Double.compare(re, c.re) == 0 &&
Double.compare(im, c.im) == 0;
}
@Override public int hashCode() {
int result = 17 + hashDouble(re);
result = 31 * result + hashDouble(im);
return result;
}
private int hashDouble(double val) {
long longBits = Double.doubleToLongBits(re);
return (int) (longBits ^ (longBits >>> 32));
}
@Override public String toString() {
return "(" + re + " + " + im + "i)";
}
}
Advantages of immutable objects
- Immutable objects are simple
- Immutable objects are inherently thread-safe; they require no synchronization
- Immutable objects can be shared freely
public static final Complex ZERO = new Complex(0, 0); public static final Complex ONE = new Complex(1, 0); public static final Complex I = new Complex(0, 1);
- Not only can you share immutable objects, but you can share their internals
- Immutable objects make great building blocks for other objects (i.e. map, set)
- The only real disadvantage of immutable classes is that they require a separate object for each distinct value