这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战
前言
本文讲解不可变类,将介绍设计不可变类的原则,不可变类作为实例不能被修改的类,在实例被创建的时候被初始化,在其生命周期中不能被修改,比如String,BigDecimal,BigInteger等,不可变类是线程安全的,接下来我们将会介绍不可变类的原则。
设计不可变类的原则
不要提供任何会修改对象状态的方法
不要提供方法可以对实例化后的不可变类进行二次修改,比如我们都使用StringBuilder来进行字符串的创建,之后再将其赋给String,而不是对同一个String做操作。
保证类不会被扩展
直接使用final对类进行修饰,防止有子类假装对象的状态已经改变,从而破坏该类的不可变行为。
声明所有的域都是final的
通过系统的强制方式可以清楚的表明你的意图
声明所有的域都是private的
想要防止使用者获得访问被引用的可变对象的权限,并防止客户端修改这些对象,那么就需要我们将对应的域都声明为private的。
确保对于任何可变组件的互斥性访问
如果类具有指向可变对象的域,则必须确保客户端无法获得指向这些对象的引用;
不可变类的优点
不可变对象线程安全
作为线程安全的对象,它们不要求同步,多个线程一起访问时不会被破坏,可以被多个线程共享。
可以共享内部信息
public BigInteger negate() {
return new BigInteger(this.mag, -this.signum);
}
复制代码
对于BigInteger而言,我们可以看到符号位使用了一个int来存储,数值使用了一个int数组来进行保存的,当我们使用negate来获得对应的负数的时候,并不是对数组进行拷贝,而是将符号取反,数组仍然使用原来的那个数组。
提供了失败的原子性
状态永远不改变,因此不存在临时不一致的可能性!
不可变类的缺点
每个不同的值都需要一个单独的对象
这就是我们要先用StringBuilder来对字符串进行各种操作,之后再赋给对应的String类的原因