使可变性最小化(15)

一、java语言支持四种类型:java

(1)接口(interface):数组

(2)类(class):缓存

(3)数组(Array):安全

(4)基本类型(primitive):惟一非引用类型(reference type)多线程

二、方法签名:包括方法名称、参数,不包括返回值;并发

《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《函数

三、不可变类性能

  • 实例不可被修改类
  • 每一个实例中包含的全部信息,必须在建立的时候提供,并在整个生命周期不可变
  • 例如:String、基本类型包装类、BigInteger、BigDecimal
  • 比可变类,易于设计使用,不易出错、更加安全

四、成为不可变类,五条规则ui

(1)不提供任何修改对象状态的方法线程

(2)保证类不会被扩展

  • 这样能够防止粗心、恶意子类,伪装对象状态已经改变;
  • 防子类化,通常使用 final 类

(3)全部的类都是 final 

  • 经过系统的强制,代表意图

(3.1)不可变类变成 final 的另外一种作法:

  • 使不可变类全部构造方法都变成私有或包级私有,添加公有静态工厂,替换公有构造器

(4)全部域都私有

  • 技术上容许不可变类具备公有 final 域(域包含基本类型值或 不可变对象引用)
  • 不建议上述作法缘由:之后版本没法改变内部表示法

(5)确保对任何可变组件的互斥访问

  • 若是类具备可变对象的域,须保证客户端没法或者这些对象的引用
  • 不要用客户端提供的对象引用初始化 可变对象的域
  • 不要从任何访问方法返回该对象引用
  • 在构造器、访问方法、readObject方法(76条)中,请使用保护性拷贝(39条)

五、函数方式的模式

  • 对操做数进行运算,但不修改,返回新建立的实例
  • 大多数不可变类都是用该模式
  • 该作法带来了不可变性
  • 约束关系在整个生命周期都不变,不须要额外代码维护约束关系

六、不可变对象本质上是线程安全的,且不要求线程同步

  • 多线程并发访问不可变类对象,不会破坏对象,线程安全最容易实现
  • 不可变对象能够被自由的共享
  • 鼓励客户端尽量重用现有实例(简单实现:频繁用到的值,提供公有静态 final 常量)
  • 对不可变类提供静态工厂<1条>,缓存公用频繁使用的实例
  • 基本类型包装类、BigDecimal等就有这样静态工厂
  • 使用静态工厂而不是公有构造器,之后添加缓存更灵活

七、不可变对象能够被自由的共享

  • 永远不须要进行保护性拷贝<39条>
  • 不该该对不可变类提供 clone 方法或 拷贝构造器<11条>
  • String类有拷贝构造器,尽可能不要使用<5条>

八、不只能够共享不可变对象,能够共享内部信息

  • 不可变类BigInteger,在使用negate()得到相反数时,内部mag指向原有对象的mag数组
  • 由于是不可变类,对象不会被修改才能够这么操做

九、不可变对象真正缺点

  • 对于每个单独的值都须要一个单独的对象;
  • 好比:一个百万位的BigInteger,运算时须要不停建立新对象,性能消耗巨大;
  • BitSet 则容许固定时间内,改变某一位

十、若是不可预测,提供公有可变嵌套

  • String类的可变公有嵌套:StringBuild(和已经基本废止的StringBuffer)

十一、若是可预测,能够采用内部可变对象,存取中间值

  • 这样,不用每一步都建立不可变对象

十二、BigInteger和BigDecimal刚北边写出来时,不可变类必须是 final 未获得普遍认同

  • 这俩类,存在被继承和被篡改的风险

1三、不可变类没有方法会修改对象,全部域必须是 final

  • 为提升性能能够有非 final 的域:第一次运算时将开销昂贵的结果保存起来,下次直接用
  • 不可变性,保证告终果的正确性

1四、序列化功能一条告诫:

  • 不可变类实现了Serializable接口,须要显式readObject等4个方法
  • 攻击者可能从不可变类建立可变对象<76条>

1五、没有好的理由,类就要作成不可变得

1六、类不能作成不可变的,也要尽可能限制其可变性;

1七、除非有好的理由,每一个域都应该是 final 的

1八、构造器和静态工厂外,不该再提供公有初始化方法

1九、不可变类不要提供从新初始化方法

相关文章
相关标签/搜索