Effective Java - 使可变性最小化

2022-05-22  本文已影响0人  DZQANN

第16条 在公有类中使用访问方法而非公有域

  1. 对公有类, 应该用包含私有域和公有访问方法(getter)的类来代替, 对可变的类, 加上公有设值方法(setter).
    -> 保留了改变内部表现的灵活性.
  2. 如果类是包级私有的, 或者是私有的嵌套类, 直接暴露它的数据域并没有本质的错误.

第17条 使可变性最小化

这一条讲的是不可变类:每个实例中包含的所有信息都必须在创建该实例的时候就提供, 并在对象的整个生命周期内固定不变。Java中比较经典的不可变类就是StringBigIntegerBigDecimal

一个不可变类的例子:

public final class Complex {
    private final double re;
    private final double im;

    public Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }

    public double realPart()      { return re; }
    public double imaginaryPart() { return im; }
}

主要就是类里面的每一个字段都用final修饰,并且在构造方法中初始化。

不可变类的5个原则

不可变类的优势

不可变类的缺点

对于每个不同的值都需要一个单独的对象. (特定情况下的性能问题.)

在构建了不可变类的同时,也可以创建配套的可变配套类,比如Java类库中的String的可变配套类是StringBuilderStringBuffer.

其它不可变类设计方案

  1. 除了将类设置为final外,也可以通过私有化构造方法,用静态工厂代替的方法使类不能被继承。这样可以提供缓存的能力

  2. 不一定所有的字段都是final的,需要满足的要求是: 没有一个方法能够对对象的状态产生外部可见的改变

    比如一个类可以有一个非final的hashCode字段,用来缓存hashCode

感想

Java14的record就是不可变类的典范。我们正常使用的VO按道理说都应该是不可变的。可是真正在使用过程中,又经常迫于无奈只能在不同的地方改变对象的状态。比如说UI可能只能识别到companyCode,而Dao又需要的是companyId,就只能在service层给criteria塞上通过code查询出来的id。

这个地方应该提醒我们的更多的是带有业务逻辑的Helper、Wrapper等等,这些类里面的成员变量都应该是final的,尤其不能提供set方法。不然在对象的传输、使用过程中,我们很难去追踪哪里可能会有副作用,导致了对象里面的内容变化。其实应该从根本上杜绝这种事情发生。包括我自己曾经有过不好的习惯,在public方法中,把形参塞到当前对象的全局变量上,为了以后其他的private方法可以不需要都传这个形参,直接读取全局变量就可以了。这其实也是一种不好的改变了当前对象状态的一种形式,而且它更加的隐晦

上一篇 下一篇

猜你喜欢

热点阅读