1. 创建和销毁对象
    1. 1. 考虑用静态工厂方法代替构造器
      1. 优势1:有名称
      2. 优势2:不必在每次调用它的时候都创建一个新的对象
      3. 优势3:可以返回子类型对象
      4. 优势4:在创建参数化类型的时候,可以是代码变得更加简洁
      5. 静态工厂方法缺点1:类如果不含公有的或者受保护的构造器,就不能被子类话
      6. 静态工厂方法缺点2:它们与其他的静态方法实际上没有任何区别
    2. 2. 遇到多个构造器参数的时候考虑用构造器
      1. 多个构造参数的问题
        1. 重叠构造器,难写难读
        2. JavaBean模式在构造过程中可能处于不一致的状态
        3. JavaBean模式阻止了把类做成不可变的可能
      2. builder模式
        1. 如果类的构造器或者静态工厂有多个参数,设计这种类的时候,Builder模式就是不错的选择
    3. 3. 用私有的构造器或者枚举类型强化Singleton属性
    4. 4. 通过私有构造器强化不可实例化的能力
    5. 5. 避免创建不必要的对象
      1. 如果对象是不可变的,他就始终可以被重用
    6. 6. 清除过期的对象引用
      1. 只要类是自己管理内存,程序员应该警惕内存泄露问题
      2. 内存泄露的另一个常见来源是缓存
      3. 内存泄露的第三个常见来源是监听器和其他回调
    7. 7. 避免使用终结方法
      1. 除非是作为安全网或者为了终结非关键的本地资源,否则不要使用终结方法
      2. 使用终结方法,就要调用super.finalize
      3. 终结方法与公有的非final类关联起来,考虑使用终结方法守卫者
  2. 对于所有对象都通用的方法
    1. 8. 覆盖equals时请遵守通用约定
      1. 不用覆盖equals方法的情况
        1. 类的每个实例本质上都是唯一的
        2. 不关心类是否提供了“逻辑相等”的测试功能
        3. 超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的
        4. 类是私有的或者是包级私有的,可以确定它的equals方法不会被调用
      2. 约定
        1. 自反省
        2. 对称性
        3. 传递性
        4. 一致性
        5. 任何非null的引用x,x.equals(null)必须返回false
      3. 高质量equals的诀窍
        1. 使用==操作符检查“参数是否为这个对象的引用”
        2. 使用instanceof操作符检查“参数是否为正确的类型”
        3. 把参数转化为正确的类型
        4. 对于该类中的每个“关键域”,检查参数中的域是否与该对象中对应的域相匹配
          1. float和double域使用Float.compare和Double.compare方法
          2. 可为空的对象引用域的比较 (field == null ? o.field == null : field.equal(o.field) 或者(field == o.field || (field != null && field.equals(o.field)))
        5. 当你编写完成了equal方法之后,应该问自己三个问题:它是否对称的,传递的,一致的
          1. 覆盖equal方法时总要覆盖hashCode
          2. 不要企图让equals方法过于智能
          3. 不要将equals声明中的Object对象替换为其他的类型,这样是重载,不是覆盖
    2. 9. 覆盖equals时总要覆盖hashCode
      1. 相等的对象必须拥有相等的散列码
        1. result = result * 31 + c
        2. hashCode()开销大时可以缓存
        3. 不要试图从散列码计算中排除掉一个对象的关键部分来提高性能
    3. 10. 始终要覆盖toString()方法
      1. toString()方法应该返回所有值得关注的信息
      2. 对象太大的时候返回一个摘要信息
      3. 无论你是否要指定格式,都要应该在文档中明确的表明你的意图,要指定格式,就要严格地这样去做
      4. 无论是否指定格式,都为toString方法返回值中包含的所有信息提供一种编程式的访问途径
    4. 11. 谨慎的覆盖clone
      1. 同构造器一样,clone方法不应该在构造的过程中调用任何非final的方法
    5. 12. 考虑实现Comparable接口
  3. 类和接口
    1. 13.使类和成员的可访问性最小化
    2. 14.在公有类中使用访问方法而非公有域
    3. 15. 使可变性最小化
      1. 不可变类
        1. 不提供任何会修改对象状态的方法
        2. 保证类不会被扩展
        3. 使所有的域都是final的
        4. 使所有的域都成为私有的
        5. 确保对于任何可变组件的互斥访问
          1. 保护性拷贝
    4. 16.复合优先于继承
      1. 安全的继承
        1. 同一个包下,由同一个程序员控制
        2. 专门为了继承而设计,并且有很好的文档
      2. 继承打破了封装性
        1. 自用性
        2. 超类升级
      3. 复合/转发
        1. 包装类
          1. decorator
    5. 17.要么为继承而设计,要么提供文档说明,要么就禁止继承
      1. 文档说明可覆盖的方法的自用性
        1. 方法或构造器调用了那些可覆盖的方法,调用顺序,调用结果,后续影响
        2. 那些情况下会调用可覆盖的方法
      2. 对于为了继承而设计的类,唯一的测试方法就是编写子类
      3. 构造器决不可调用可被覆盖的方法
    6. 18.接口优于抽象类
      1. 现有的类很容易被更新,以实现新的接口
      2. 接口是定义mixin的理想选择
      3. 接口允许我们构造非层次结构的类型框架
      4. !抽象类的演变要比接口容易的多
        1. 接口一旦被发行,并且已经被广泛实现,再想改变这个接口几乎是不可能的
    7. 19.接口只用于定义类型
      1. 常量接口会污染命名空间
    8. 20.类层次优于标签类
    9. 21.用函数对象表示策略
    10. 22.优先使用静态成员类
      1. 四种嵌套类(nested class)
        1. 静态成员类
        2. 非静态成员类
        3. 匿名类
        4. 局部类
  4. 泛型
    1. 23.请不要在新代码中使用原生态类型
      1. 声明中有一个或多个类型参数(type parameter)的类或者接口,就是泛型(generic)类或者接口
      2. 无限制的通配符类型(?),不能讲任何元素(null除外)放到Collection<?>中,否则会有编译时异常
      3. 例外
        1. 类文字(class literal)中必须使用原生态类型
          1. List.class, String[].class, int.class合法,List<String>.class,List<?>.class不合法
          2. instanceof 操作符
    2. 24.消除非首检警告
    3. 25.列表优于数组
      1. 数组是协变的,泛型则是不可变的
    4. 26.优先考虑泛型
      1. 使用泛型比使用需要在客户端进行转换的类型来的更加安全,也更加容易。在设计新的类型的时候,要确保它们不需要这种转换就可以使用。
    5. 27.优先使用泛型方法
      1. 静态工具方法尤其适合于泛型化
      2. 泛型单例工厂
      3. 递归类型限制
    6. 28. 利用有限制的通配符来提升API的灵活性
      1. PECS
    7. 29. 优先考虑安全的异构容器
  5. 枚举和注解
    1. 30. 用enum代替int常量
      1. int枚举模式类型不安全,不方便使用
      2. String枚举类型不安全,有性能问题
      3. 枚举类型可以带构造器,带方法,可以带抽象方法还可以嵌套
    2. 31. 用实例域代替序数
    3. 32. 用EnumSet代替位域
      1. Enum.ordinal很少用到
    4. 33. 用EnumMap代替序数索引
    5. 34. 用接口模拟可伸缩的枚举
    6. 35. 注解优于命名模式
      1. JUnit新旧版本
      2. 命名方式缺点
        1. 文字拼写错误会导致失败
        2. 无法确保它们只用于相应的程序元素上
        3. 没有提供将参数值与程序元素关联起来的好方法
      3. 注解
        1. 元注解
        2. 标记注解
    7. 36. 坚持使用Override注解
    8. 37. 用标记接口定义类型
  6. 方法
    1. 38. 检查参数的有效性
      1. 公有的方法,参数限制要写文档,参数无效抛出IllegalArgumentException,IndexOutOfBoundsException,NullPointerException的异常
      2. 非公有的方法通过断言来检查他们的参数
      3. 构造器的参数有效性检查是非常重要的
      4. 例外:检查昂贵,不切实际,隐含在计算过程中
    2. 39. 必要时进行保护性拷贝
      1. TOCTOU攻击
      2. 对于参数类型可以被不可信任方子类化的参数,请不要使用clone方法进行保护性拷贝
    3. 40. 谨慎的设计方法签名
      1. 谨慎的选择方法的名称
      2. 不要过于追求提供便利的方法
      3. 避免过长的参数列表
        1. 方法分解
        2. 辅助类
        3. 从对象创建到方法调用都采用builder模式
      4. 对于参数类型,要优先使用接口而不是类
      5. 对于boolean类型的参数,要优先使用两个元素的枚举类型
    4. 41. 慎用重载
    5. 42. 慎用可变参数
      1. printf和反射机制从变长参数中大大的受益
      2. 会影响一些性能
    6. 43. 返回0长度的数组或集合,而不是null
    7. 44. 为所有导出的api编写文档注释
  7. 通用程序设计
    1. 45.将局部变量的作用域最小化
      1. 在第一次使用它的地方声明
    2. 46.for-each循环优于传统的for循环
      1. for-each可以遍历集合和数组以及任何实现了iterable接口的对象
      2. 无法使用for-each的地方
        1. 过滤
        2. 转换
        3. 平行迭代
    3. 47.了解和使用类库
      1. java.lang
      2. java.util
    4. 48.如果想要精确的答案,请避免使用float和double
      1. 货比计算使用BigDecimal,int或者long
    5. 49.基本类型优于装箱基本类型
    6. 50.如果其他类型更适合,则尽量避免使用字符串
      1. 字符串不适合代替其他值类型
      2. 字符串不合适代替枚举类型
      3. 字符串不适合代替聚集类型
      4. 字符串不适合代替能力表
    7. 51.当心字符串连接的性能
    8. 52.通过接口引用对象
    9. 53.接口优于反射机制
      1. 丧失了编译时类型检查的好处
      2. 执行反射访问所需要的代码非常笨拙和冗长
      3. 性能损失
    10. 54.谨慎的使用本地方法
    11. 55.谨慎的进行优化
      1. 很多计算上的过失都被归咎于效率(没有必要达到的效率),而不是任何其他的原因--甚至包括盲目的做傻事 --William A. Wulf
      2. 不要去计较效率上的一些小小的损失,在97%的情况下,不成熟的优化才是一切问题的根源 --Donald E. Knuth
      3. 在优化方面,我们应该遵守两条规则:规则1:不要进行优化。 规则二:(仅针对专家):还是不要进行优化--也就是说,在你还没有绝对清晰的未优化方案之前,请不要进行优化 --M. A. Jackson
      4. 不要费力去编写快的程序,应该努力编写好的程序
    12. 56.遵守普遍接受的命名惯例
  8. 异常
    1. 57. 只针对异常的情况才使用异常
      1. 永远不应该用于正常的控制流
      2. 设计良好的API不应该强迫它的客户端为了正常的控制流而使用异常
    2. 58. 对可恢复的情况使用受检异常,对编程错误使用运行时异常
      1. 大多数运行时异常都表示提前违例
    3. 59. 避免不必要的使用受检异常
    4. 60. 优先使用标准的异常
      1. 常用异常
        1. IllegalArgumentException
        2. IllegalStateException
        3. NullPointerException
        4. IndexOutOfBoundsException
        5. ConcurrentModificationException
        6. UnsupportedOperationException
    5. 61. 抛出与抽象对应的异常
      1. 异常转义,异常链
    6. 62. 每个方法抛出的异常都要有文档
      1. 要为每个受检异常提供单独的throws子句,不要为未受检异常提供throws子句
    7. 63. 在细节信息中包含能补获失败的信息
    8. 64. 努力使失败保持原子性
      1. 不可变对象
      2. 执行操作之前检查参数有效性,可能会失败的计算部分都在对象状态被修改之前发生
      3. 编写恢复代码,临时拷贝
    9. 65. 不要忽略异常
  9. 并发
    1. 66. 同步访问共享的可变数据
      1. 同步
        1. 互斥
        2. 通信
          1. volatile
          2. i++不是原子操作
          3. java.util.concurrent.atomic.AtomicLong
          4. 两种失败
          5. 活性失败(程序无法进行)
          6. 安全性失败(程序计算出错误的结果)
    2. 67. 避免过度同步
      1. 为了避免活性失败或者安全性失败,在一个被同步的方法或者代码块中,永远不要放弃对客户端的控制
      2. 应该在同步区域内做尽可能少的工作
        1. 获得锁,检查共享数据,根据需要转换数据,然后放掉锁
        2. 如果一个可变的类要并发使用,应该使这个类变成事线程安全的,通过内部同步,你还可以获得明显比外部锁定整个对象更高的并发性。否则,就不要在内部同步,让客户在必要的时候从外部同步
        3. 在同步区域之外被调用的外来方法被称作“开发调用”
    3. 68. executor和task优先于线程
      1. Executor Framework
        1. java.util.concurrent.Executors
    4. 69. 并发工具优先于wait和notify
      1. java.util.concurrent中的工具分成三类
        1. Executor Framework
        2. Concurrent Collection(并发集合)
        3. Synchronizer(同步器)
    5. 70. 线程安全性的文档化
      1. 线程安全级别
        1. 不可变的
          1. String
          2. Long
          3. BigInteger
        2. 无条件的线程安全
          1. Random
          2. ConcurrentHashMap
        3. 有条件的线程安全
          1. Collections.synchronized包装返回的集合,他们的迭代器要求外部同步
        4. 非线程安全
          1. ArrayList
          2. HashMap
        5. 线程对立的
    6. 71. 慎用延迟初始化
      1. 对于实例域,使用双重检查模式
      2. 对于静态域,使用Lazy initialization holder class idiom
      3. 对于可以接受重复初始化的实力域,也可以考虑使用单重检查模式
    7. 72. 不要依赖线程调度器
      1. 任何依赖于线程调度器来达到正确性或者性能要求的程序,很有可能都是不可移植的
    8. 73. 避免使用线程组
  10. 序列化
    1. 74. 谨慎的实现Serializable接口
      1. 三个代价
        1. 大大降低了“改变这个类的实现”的灵活性
        2. 增加了bug和安全漏洞的可能性
        3. 随着类发行新的版本,相关的测试负担也增加了
      2. Date,BigInteger这样的值类应该实现Serializable,大多数的集合类也应该如此。
      3. 代表活动实体的类,比如线程池,一般不应该实现Serializable
    2. 75. 考虑使用自定义的序列化形式
      1. 如果一个对象的物理表示法等同于它的逻辑内容,可能就适合于使用默认的序列化形式。
      2. 当一个对象的屋里表示法与他的逻辑数据内容有实质性的区别时,使用默认的序列化形式会有以下4个缺点
        1. 它使这个类的导出API永远的束缚在该类的内部表示上
        2. 它会消耗过多的空间
        3. 它会消耗过多的时间
        4. 它会引起栈溢出
      3. 不使用默认的序列化形式
        1. writeObject
        2. readObject
        3. transient
      4. 不管选择了那种序列化的形式,都要为自己编写的每个可序列花的类声明一个显式的序列版本UID
    3. 76. 保护性的编写readObject方法
    4. 77. 对于实例控制,枚举类型优于readResolve
      1. 对于一个正在被反序列化的对象,如果它的类定义了一个readResolve方法,并且具备正确的声明,那么在反序列化之后,新建对象上的readResolve方法就会被调用,然后,该方法返回的对象引用将被返回,取代新建的对象
      2. 如果依赖readResolve进行实例控制,带有对象引用类型的所有实力域都必须为transient。
    5. 78. 考虑序列化代理代替序列化实例
      1. writeReplace方法