Effective Java2-学习笔记 第11-20条

11.谨慎地覆盖clone

  • 若是能够用拷贝构造器或拷贝工厂代替

12.考虑实现Comparable接口

  • 值类存在很是明显的内在排序关系,就应该坚定考虑实现这个接口
  • 保持和equals()的一致性
  • 当该对象小于,等于或大于指定对象的时候,分别返回一个负整数,零或者正整数.若是因为指定对象的类型而没法与该对象进行比较,则抛出ClassCastException异常
  • 若是非零差值不会溢出,则能够直接return这个插值

13.使类和成员的可访问性最小化

  • 尽量地使每一个类或者成员不被外界访问
  • 若是你把它作成公有的,你就有责任永远支持它,以保持它们的兼容性
  • 受保护的成员应该尽可能少用
  • 可让测试做为被测试的包的一部分来运行,从而可以访问它的包级私有的元素
  • 若是域是非final的,或者是一个指向可变对象的final引用,那么一旦使这个域成为公有的,就放弃了对存储在这个域中的值进行限制的能力,这意味着,你也放弃了域不可变的能力.同时,当这个域被修改的时候,你也失去了对它采起任何行动的能力.所以,包含公有可变域的类并非线程安全的.
  • 若是final域包含可变对象的引用,它即是final域的全部缺点.虽然引用自己不能被修改,可是它所引用的对象倒是能够被修改-这会致使灾难性的后果
  • 类具备公有的静态final数组域,或者返回这种域的访问方法,这几乎老是错误的.若是类具备这样的域或者访问方法,客户端将可以修改数组中的内容.这是安全漏洞的一个常见根源,解决:1.可使公有数组变成私有的,并增长一个公有的不可变列表  2.使数组变成私有的,并增添一个公有方法,它返回私有数组的一个备份

14.在公有类中使用访问方法而非共有域

  • 若是公有类暴露了它的数据域,要想在未来改变其内部表示法是不可能的,由于公有类的客户端代码已经遍及各处了.
  • 若是类是包级私有的嵌套类,直接暴露它的数据域并无本质的错误-假设这些数据确实描述了改类所提供的抽象.
  • 在私有嵌套类的状况下,改变的做用域范围被进一步限制在外围类中.
  • 若是不改变类的API,就没法改变这种类的表示法.

15.使可变性最小

不可变的类比可变类更加易于设计,实现和使用.它们不容易出错,且更加安全.编程

为了使类更为不可变,要遵循下面五条规则:数组

  1. 不要提供任何会修改对象状态的方法.
  2. 保证类不会被扩展.
  3. 使全部的域都是final的.
  4. 使全部的域都成为私用的.
  5. 确保对于任何可变组件的互斥访问.
    • 若是类具备指向可变对象的域,则必须确保该类的客户端没法得到指向这些对象的引用.
    • 永远不要用客户端提供的对象引用来初始化这样的域,也不要从任何访问方法中返回该对象引用.
    • 在构造器,访问方法和readObject方法中请使用保护性拷贝技术
  • 不可变对象本质上是线程安全的,它们不要求同步.
  • 不可变对象能够被自由地共享,永远也不须要进行保护性拷贝.
  • 不只能够共享不可变对象,甚至也能够共享它们的内部信息.
  • 不可变对象为其余对象提供大量的构件.
  • 不可变类真正惟一的缺点是,对于每一个不一样的值都须要一个单独的对象.

若是你执行一个多步骤的操做,而且每一个步骤都会产生一个新的对象,除了最后的结果以外其余的对象最终都会被丢弃,此时性能问题就会显露出来.缓存

  1. 解决,先猜想一下会常常用到哪些多步骤的操做,而后将它们做为基本类型提供.若是某个多步骤操做已经做为基本类型提供,不可变的类就能够没必要在每一个步骤单首创建一个对象.
  2. 解决,若是能精确地预测出客户端将要在不一样的类上执行哪些复杂的多阶段操做,这种包级私有的可变配套类的方法就能够工做的很好.若是没法预测,最好的方法是提供一个公有的可变配套类.
  • 让不可变的类编程final的另外一种方法就是,让类的全部构造器都变成私有的或者包级私有的,并添加公有的静态工厂来代替公有的构造器
    • 这种方法还使得有可能经过改善静态工厂的对象缓存能力,在后续的发行版本中改进该类的性能.
    • 工厂的名字能够清楚地代表它的功能.
  • 若是你在编写一个类,它的安全性依赖于(来自不可信客户端的)BigInteger或者BigDecimal参数的不可变性,就必须进行检查,以肯定这个参数是否为"真正"的BigInteger或者BigDecimal,而不是不可信子类的实例.若是是后者的话,就必须在假设它多是可变的前提下对它进行保护性拷贝
  • 除非有很好的理由要让类成为可变的类,不然就应该是不可变的.惟一的缺点是在特定的状况下存在潜在的性能问题.
  • 所以,除非有使人信服的理由要使域变成是非final的,不然要使每一个域都是final的.
  • 构造器应该建立彻底初始化的对象,并创建起全部的约束关系.与所增长的复杂性相比,"从新初始化"方法一般并无带来太多的性能优点.
相关文章
相关标签/搜索