第15条:使可变性最小化
如何使类成为不可变的
- 不要提供任何会修改对象状态的方法 即setter
- 保证类不会被扩展 一般使这个类成为final的
- 使所有域都是final的
- 使所有域成为私有的
- 确保对于任何可变组件的互斥访问 readObject方法中使用保护性拷贝
public final class Complex {
private final double re;
private final double im;
public Complex(double re, double im) {
super();
this.re = re;
this.im = im;
}
public double realPart() {return re;}
public double imaginaryPart() {return im;}
//没有提供setter方法
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(c.re * 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,(re * c.re - im * c.im)/tmp);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(im);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(re);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Complex other = (Complex) obj;
if (Double.doubleToLongBits(im) != Double.doubleToLongBits(other.im))
return false;
if (Double.doubleToLongBits(re) != Double.doubleToLongBits(other.re))
return false;
return true;
}
@Override
public String toString() {
return "Complex [re=" + re + ", im=" + im + "]";
}
}
每次运算都返回新的Cpmplex实例,而不是修改这个实例,它被称为函数的做法
优点:
- 不可变对象本质上是线程安全的,它们不要求同步,不可变 对象可以被共享
- 不公可以共享对象,也可以共享他们的内部信息
- 不可变对象 为其它对象提供了大量的构件
缺点:
对于每一个值都需要一个单独的对象
还有一种更加灵活的方法:
public class ComplexOther {
private final double re;
private final double im;
private ComplexOther(double re,double im) {
this.re = re;
this.im = im;
}
public static ComplexOther getInstance(double re,double im) {
return new ComplexOther(re,im);
}
}
这种方式的好处:
1.允许使用多个包级实现类
2.可以提供缓存能力
3.具有静态工厂的优势