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 麦肯锡问题解决方法与技巧
  3. 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

1.2.10 INPROGRESS ng-book2

1.2.11 INPROGRESS Combo #3: SLAM

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-09-05 Wed 10:55

Emacs 25.3.2 (Org mode 8.2.10)

Validate