非可变类就是类的实例不能被修改的类。如String。
非可变类有很多好的存在理由非可变类更容易设计、实现和使用
不易犯错误
更安全
为了使类成为非可变的,要遵循下面5条原则不要提供任何修改对象的方法。
保证没有可以被重载的方法。这防止了粗心的或恶意的子类危害对象的不可变行为。防止方法被重载的一般方式是是类成为final的。
使所有的域成为final。
使所有的域都是私有的。
保证对任何可变组件互斥访问。
下面是一个稍微复杂的例子:
public final class Complex {
private final float re;
private final float im;
public Complex(float re, float im) {
this.re = re;
this.im = im;
}
public float realPart() { return re; }
public float imaginaryPart() { return im; }
public Complex add(Complex c) {
return new Complex(re+c.re,im+c.im);
}
...
public boolean equals(Object o) {
if(o==this)
return true;
if(!(o instanceOf Complex))
return false;
Complex c = (Complex) 0;
return(Float.floatToIntBits(re) == Float.floatToIntBits(c.re) ) &&
(Float.floatToIntBits(im) == Float.floatToIntBits(c.im));
}
public int hashCode() {
int result = 17 + Float.floatToIntBits(re);
result = 37*result + Float.floatToIntBits(im);
return result;
}
public String toString() {
return "("+re+" + "+im+"i)";
}
}
这个类表示复数,注意到算术操作创建和返回一个新的复数实例,而不是修改了这个实例。
非可变对象本质上是线程安全的,不需要同步机制。这是获得线程安全最简单的途径。线程不会看到其他线程对非可变对象施加的影响,因而,非可变对象可以被自由地共享。
非可变对象可以提供一个静态工厂,将经常被请求的实例缓存起来,避免在被请求的实例存在时,重复地创建新的实例。BigInteger和Boolean类都具有这种静态工厂方法。
不仅可以共享非可变对象,还可以共享它们的内部信息。
非可变对象为其他对象——无论是可变还是非可变的,创建了大量的构造块。
非可变对象的真正也是唯一的缺点是对每个不同的值要求一个单独的对象。