1.1 不可变类
不可变类是指其实例创建后状态不能被修改的类。它们的实例信息是由调用构造函数时就提供,不会提供对外的设值方法,保证它们的状态不会被改变。
1.1.1 不可变类的好处
在Java平台类库中包含许多不可变的类,如String、基本类型的包装类以及Collections工具类中Unmodifiable对应各种集合的实现。不可变类比可变类更加易于设计、实现和使用,不容易出错,且更加安全。
- 不可变对象很简单,因为只有一种状态(创建时的状态)
- 不可变对象可以被自由的共享
- 不可变对象一定是线程安全的,它们不需要额外的同步......
1.1.2 不可变类的设计规则
- 不提供对外修改对象状态的设值方法
- 声明的所有域都是final类型^
- 保证类不会被扩展,正确的被创建
需要注意:并不是所有的域都必须声明为final类型,具体可参考String类中的hash字段;即使对象中的所有的域都是final类型的,也不能保证对象是不可变的,因为在final类型的域中可能指向的是可变对象。
1.1.3 不可变类的具体设计
public class ImmutableClass {
private final int x;
private final int y;
private int hash; // 缓存hashcode,内部计算可能发生改变但是不会对外提供
// final域指向的是可变对象,不能返回该对象引用(或者使用深拷贝) ❌
// private final List<Integer> list = new ArrayList<>();
private final List<Integer> list = Collections.unmodifiableList(Arrays.asList(1,2));
/*
* 缓存对象
*/
public static final ImmutableClass ZERO_ONE = new ImmutableClass(0, 1);
public static final ImmutableClass ONE_TWO = new ImmutableClass(1, 2);
// 使用 静态工厂方法+私有构造器 使类变成final
private ImmutableClass(int x, int y) {
this.x = x;
this.y = y;
}
public static ImmutableClass valueOf(int x, int y) {
return new ImmutableClass(x, y);
}
public ImmutableClass plus(ImmutableClass u) {
return new ImmutableClass(x + u.x, y + u.y);
}
public ImmutableClass minus(ImmutableClass u) {
return new ImmutableClass(x - u.x, y - u.y);
}
//....
public int getX() {
return x;
}
public int getY() {
return y;
}
public List<Integer> getList() {
return list;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof ImmutableClass))
return false;
ImmutableClass u = (ImmutableClass)obj;
return Integer.compare(u.x, x) == 0
&& Integer.compare(u.y, y) == 0;
}
@Override
public int hashCode() {
int result = hash;
if (result == 0) {
result = Objects.hash(x,y);
hash = result;
}
return result;
}
}
总结
如果某个对象在被创建后其状态不能被修改,那么这个对象就称为不可变对象。不可变类唯一的缺点就是:对于每个不同的值都需要去创建一个新对象。
参考书籍:《Effective Java》