使可变性最小化--EffectiveJava小结(15)

不可变类:每个实例的所有属性都必须再创建该实例时就提供,并且再对象的整个生命周期内固定不变。

不可变类的五个规则:
1.不提供任何修改属性的方法。
2.保证类不会被扩展。
(不是不能子类化,而是为了防止调用者将其子类化)
3.所有属性都是final修饰。
4.所有属性都私有。(1.当属性是可变对象时候,防止调用方获取该可变对象并且修改了其属性。2.通过方法比直接提供属性更灵活,方法可以修改其内部实现)
5.确保对于任何可变对象的互斥访问。(1.这里的互斥访问指的是:这个不可变对象,和被这个不可变对象属性所指向的可变对象,调用方只能获取到其中之一。2.基于互斥访问,也就是说不要用调用方提供的可变对象来初始化这个不可变对象,可以通过深拷贝来做)

不可变对象的优点:
1.线程安全。
2.可被自由共享。
(而不需要通过深拷贝来保护原对象,利用这个优点,对于常用值可以提供静态final常量)
3.不可变对象为其他对象提供了大量构件。(不容易读懂这句话,结合上下文理解就是复杂对象使用不可变对象比使用可变对象省心多了,想一下一个属性是不可变对象String, 一个是可变对象obj,然后要实现clone方法,不可变对象直接赋值就搞定了,可变对象还要考虑其内部的引用)。

唯一缺点: 每个不同的值都需要一个单独的对象。
1.对象比较大的话,对象创建代价显得比较高。比如两个上百万位的BigInteger对象,可能区别只是个位数不同,但需要两个对象。
2.多步骤的操作,每一步都会产生一个结果,可只需要最后一步的结果。这种情况可以考虑使用可变配套类。如String和StringBuilder.

性能优化
规则1和3:不提供方法修改属性,所有属性都是final修饰。
为了性能优化可以放松要求:没有一个方法能够对对象的状态产生外部可见的改变。

许多不可变类都拥有非final属性,用于缓存一些开销昂贵的计算结果,为了节约再次计算的开销。因为对象的不可变性保证了这些计算再算一次也是相同的值,所以可以这么做。

你可能感兴趣的:(使可变性最小化--EffectiveJava小结(15))