不可变类是什么?
不可变类指的是实例不能被修改的类,实例中的信息都必须在创建时提供,并在其生命周期中保持不变,如String、包装类、BigInteger、BigDecimal
编写不可变类要求:
- 不提供 setter() 方法
- 保证类不会被扩展,一般做法是声明为 final
- 类中的域都为 private final
- 确保对域所指向的可变对象互斥访问(其他类无法获取该域的引用)
优缺点
优点:
- 比较简单,始终为被创建时的状态
- 线程安全,不需要同步,故可被共享(内部信息也可共享)
- 提供了原子性,不存在状态不一致的情况
缺点:
- 每个实例都需要一个单独的对象
若在一个操作中产生多个临时的不可变对象,会造成性能浪费,解决办法:
- 将中间生成的不可变对象转变为可变对象(如Integer换成int)
- 提供一个可变的对应类,如String的对应可变类为StringBuilder
通过final实现
如下复数类Complex只提供了getter()方法,定义了一个加法运算(不修改当前对象,而是返回新的实例,名字使用介词plus而不是动词add)
final class Complex {
private final double re;
private final double im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
public double realPart() {
return re;
}
public double imaginaryPart() {
return im;
}
public Complex plus(Complex c) {
return new Complex(re + c.re, im + c.im);
}
}
其他实现
让构造函数私有化,暴露公有静态工厂创建实例
class Complex {
private final double re;
private final double im;
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);
}
}