Effective Java

Table of Contents

1

1.1 Meta Notes

1.2 Books

1.2.1 DONE Combo #1

  1. DONE 金字塔原理
  2. TODO Beast Machines: Transformers (cartoon)
  3. DONE 论持久战
  4. DONE 一看就懂的经济常识全图解
  5. DONE 刻意练习
  6. DONE 系统之美
  7. DONE 邓小平时代

1.2.2 INPROGRESS Combo #2

  1. DONE 新经济, 新规则 (Kevin Kelly)
  2. DONE 麦肯锡问题解决方法与技巧

1.2.5 INPROGRESS Effective Java

1.2.6 DONE Don't Make Me Think

1.2.7 DONE Clean Code

1.2.8 INPROGRESS Deep Learning

1.2.9 INPROGRESS Async JavaScript

2 Intro

  • Effective Java (douban)

    本书介绍了在 Java 编程中 78 条极具实用价值的经验规则,这些经验规则涵 盖了大多数开发人员每天所面临的问题的解决方案。通过对 Java 平台设计专 家所使用的技术的全面描述,揭示了应该做什么,不应该做什么才能产生清晰、 健壮和高效的代码。本书中的每条规则都以简短、独立的小文章形式出现,并 通过例子代码加以进一步说明。本书内容全面,结构清晰,讲解详细。可作为 技术人员的参考用书。

2.1 译者序

2.2

2.3 前言

2.4 致谢

3 第 1 章 引言

4 第 2 章 创建和销毁对象

4.1 第 1 条:考虑用静态工厂方法代替构造器

  • static factory method 的一大优势
    • 有名字
    • 可以不必每次都创建一个对象, 比如 Collections.emptyList() 每次都是取一个静态变量, 这个变量的类型还是一个简化的 List.
    • 可以返回子类型
    • 如果 type inference 做得好, 还可以让代码更简洁. 比如 new ArrayList<>() 这样的语法
  • 当然也有缺点, 1) 不能被继承; 2) 与其他静态方法没区别, 从语法上不像构造函数那样与众不同;

4.2 第 2 条:遇到多个构造器参数时要考虑用构建器

  • 构造参数多了, 说明要配置的地方多, 用 builder 加上 fluent API 要简便得多
  • 与其弄一个大而全的 ctor, 不如每次都只配置一个点, 最后再 build 出来一个对象
  • 而且… 这种 builder 还能通过 lomock 之类的库, 加一个 annotation 就能自动生成 builder, 方便极了

4.3 第 3 条:用私有构造器或者枚举类型强化 Singleton 属性

  • 静态 final public 对象可能被篡改
  • 静态 private 加上一个 public 接口函数 (optionally 加上 lazy 初始化) 要靠谱些
  • 比上面更靠谱的是 Enum 对象, 一个 Enum 和 Class, 定义上没啥区别, 都可以有函数, 但 Enum 里面可以定义一个对象 (像是一个 label)

4.4 TODO 第 4 条:通过私有构造器强化不可实例化的能力

4.5 第 5 条:避免创建不必要的对象

  • Boolean.valueOf(ref) 几乎总是优于 new Boolean(ref), 字面量则更好
  • lazily initialling
  • map 对象返回 keySet 的时候总是返回同一个 object (不用担心性能问题)
  • 小心 autoboxing, autounboxing

4.6 第 6 条:消除过期的对象引用

  • weak reference

4.7 第 7 条:避免使用终结方法

  • 如题

5 第 3 章 对于所有对象都通用的方法

5.1 第 8 条:覆盖 equals 时请遵守通用约定

  • 这个 IDE 会帮你, 有一些原则
  • 非空, reflexive (自反), symmetric (对称), transitive (传递性), consistent (一致性)
  • TODO liskov substitution principle

5.2 第 9 条:覆盖 equals 时总要覆盖 hashCode

  • equals 的东西, hashCode 应当一致
  • hashCode 一致的 object, 不一定 equals
  • 小心计算 hashCode 时候偷懒可能引起的性能问题, 比如 string 的 hashCode 以前用的是前 16 个字符 (Java 1.2 以前), 这样用来放 url 就严重地冲突了

5.3 第 10 条:始终要覆盖 toString

  • 如题

5.4 第 11 条:谨慎地覆盖 clone

  • 写成 VO 最好
  • 提供 from 函数最好
  • 用 copy ctor 也不错
  • clone 大多数情况写没必要
  • 不要试图实现这个接口, 麻烦死

5.5 第 12 条:考虑实现 Comparable 接口

  • 泛型函数可能用到
  • 其实看情况, 我觉得没必要实现, 因为 sort (举个例子) 的时候, 每次用到的 compare 原则可能不一样啊, 临时写一个也行的
  • o1 < o2 / o1.compareTo(o2) < 0, 会升序排列

6 第 4 章 类和接口

6.1 第 13 条:使类和成员的可访问性最小化

  • information hiding / encapsulation

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

6.3 第 15 条:使可变性最小化

6.4 第 16 条:复合优先于继承

6.5 第 17 条:要么为继承而设计,并提供文档说明,要么就禁止继承

6.6 第 18 条:接口优于抽象类

6.7 第 19 条:接口只用于定义类型

6.8 第 20 条:类层次优于标签类

6.9 第 21 条:用函数对象表示策略

6.10 第 22 条:优先考虑静态成员类

7 第 5 章 泛型

7.1 第 23 条:请不要在新代码中使用原生态类型

7.2 第 24 条:消除非受检警告

7.3 第 25 条:列表优先于数组

7.4 第 26 条:优先考虑泛型

7.5 第 27 条:优先考虑泛型方法

7.6 第 28 条:利用有限制通配符来提升 API 的灵活性

7.7 第 29 条:优先考虑类型安全的异构容器

8 第 6 章 枚举和注解

8.1 第 30 条:用 enum 代替 int 常量

8.2 第 31 条:用实例域代替序数

8.3 第 32 条:用 EnumSet 代替位域

8.4 第 33 条:用 EnumMap 代替序数索引

8.5 第 34 条:用接口模拟可伸缩的枚举

8.6 第 35 条:注解优先于命名模式

8.7 第 36 条:坚持使用 Override 注解

8.8 第 37 条:用标记接口定义类型

9 第 7 章 方法

9.1 第 38 条:检查参数的有效性

9.2 第 39 条:必要时进行保护性拷贝

9.3 第 40 条:谨慎设计方法签名

9.4 第 41 条:慎用重载

9.5 第 42 条:慎用可变参数

9.6 第 43 条:返回零长度的数组或者集合,而不是:null

9.7 第 44 条:为所有导出的 API 元素编写文档注释

10 第 8 章 通用程序设计

10.1 第 45 条:将局部变量的作用域最小化

10.2 第 46 条:for-each 循环优先于传统的 for 循环

10.3 第 47 条:了解和使用类库

10.4 第 48 条:如果需要精确的答案,请避免使用 float 和 double

10.5 第 49 条:基本类型优先于装箱基本类型

10.6 第 50 条:如果其他类型更适合,则尽量避免使用字符串

10.7 第 51 条:当心字符串连接的性能

10.8 第 52 条:通过接口引用对象

10.9 第 53 条:接口优先于反射机制

10.10 第 54 条:谨慎地使用本地方法

10.11 第 55 条:谨慎地进行优化

10.12 第 56 条:遵守普遍接受的命名惯例

11 第 9 章 异常

11.1 第 57 条:只针对异常的情况才使用异常

11.2 第 58 条:对可恢复的情况使用受检异常,对编程错误使用运行时异常

11.3 第 59 条:避免不必要地使用受检的异常

11.4 第 60 条:优先使用标准的异常

11.5 第 61 条:抛出与抽象相对应的异常

11.6 第 62 条:每个方法抛出的异常都要有文档

11.7 第 63 条:在细节消息中包含能捕获失败的信息

11.8 第 64 条:努力使失败保持原子性

11.9 第 65 条:不要忽略异常

12 第 10 章 并发

12.1 第 66 条:同步访问共享的可变数据

12.2 第 67 条:避免过度同步

12.3 第 68 条:executor 和 task 优先干线程

12.4 第 69 条:并发工具优先于 wait 和 notify

12.5 第 70 条:线程安全性的文档化

12.6 第 71 条:慎用延迟初始化

12.7 第 72 条:不要依赖于线程调度器

12.8 第 73 条:避免使用线程组

13 第 11 章 序列化

13.1 第 74 条:谨慎地实现 Serializable 接口

13.2 第 75 条:考虑使用自定义的序列化形式

13.3 第 76 条:保护性地编写 readObject 方法

13.4 第 77 条:对于实例控制,枚举类型优先于 readResolve

13.5 第 78 条:考虑用序列化代理代替序列化实例

14 附录 第 1 版与第 2 版条目对照

15 中英文术语对照

16 参考文献

Author: TANG ZhiXiong

Created: 2018-01-25 Thu 12:45

Emacs 25.3.1 (Org mode 8.2.10)

Validate