类和接口-使可变性最小化

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

前言

本文讲解不可变类,将介绍设计不可变类的原则,不可变类作为实例不能被修改的类,在实例被创建的时候被初始化,在其生命周期中不能被修改,比如String,BigDecimal,BigInteger等,不可变类是线程安全的,接下来我们将会介绍不可变类的原则。

设计不可变类的原则

不要提供任何会修改对象状态的方法

不要提供方法可以对实例化后的不可变类进行二次修改,比如我们都使用StringBuilder来进行字符串的创建,之后再将其赋给String,而不是对同一个String做操作。

保证类不会被扩展

image.png 直接使用final对类进行修饰,防止有子类假装对象的状态已经改变,从而破坏该类的不可变行为。

声明所有的域都是final的

image.png 通过系统的强制方式可以清楚的表明你的意图

声明所有的域都是private的

image.png 想要防止使用者获得访问被引用的可变对象的权限,并防止客户端修改这些对象,那么就需要我们将对应的域都声明为private的。

确保对于任何可变组件的互斥性访问

如果类具有指向可变对象的域,则必须确保客户端无法获得指向这些对象的引用;

不可变类的优点

不可变对象线程安全

作为线程安全的对象,它们不要求同步,多个线程一起访问时不会被破坏,可以被多个线程共享。

可以共享内部信息

image.png

public BigInteger negate() {
    return new BigInteger(this.mag, -this.signum);
}
复制代码

对于BigInteger而言,我们可以看到符号位使用了一个int来存储,数值使用了一个int数组来进行保存的,当我们使用negate来获得对应的负数的时候,并不是对数组进行拷贝,而是将符号取反,数组仍然使用原来的那个数组。

提供了失败的原子性

状态永远不改变,因此不存在临时不一致的可能性!

不可变类的缺点

每个不同的值都需要一个单独的对象

这就是我们要先用StringBuilder来对字符串进行各种操作,之后再赋给对应的String类的原因

猜你喜欢

转载自juejin.im/post/7034880193797816350
今日推荐