Skip to content

Commit

Permalink
add Article 8 for Effective Java
Browse files Browse the repository at this point in the history
  • Loading branch information
joyang1 committed Jul 10, 2019
1 parent d418639 commit 8af8def
Showing 1 changed file with 25 additions and 1 deletion.
26 changes: 25 additions & 1 deletion docs/effective-java.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,4 +521,28 @@ public class Foo {

注意,共有类 Foo 并没有终结方法(除了它从 Object 中继承了一个无关紧要的之外),所以子类的终结方法是否调用 super.finalize() 并不重要。对于每一个带有终结方法的非 final 共有类,都应该考虑使用这种方法。

总之,除非是作为安全网,或者是为了终止非关键的本地资源,否则请不要使用终结方法。在很少见的情况下,既然使用了终结方法,就要记住调用 super.finalize。如果用终结方法作为安全网,要记得记录终结方法的非法用法。最后,如果需要把终结方法与共有的非 final 类关联起来,请考虑使用终结方法守卫者,以确保即使子类的终结方法未能调用 super.finalize,该终结方法也会被执行。
总之,除非是作为安全网,或者是为了终止非关键的本地资源,否则请不要使用终结方法。在很少见的情况下,既然使用了终结方法,就要记住调用 super.finalize。如果用终结方法作为安全网,要记得记录终结方法的非法用法。最后,如果需要把终结方法与共有的非 final 类关联起来,请考虑使用终结方法守卫者,以确保即使子类的终结方法未能调用 super.finalize,该终结方法也会被执行。

## 第三章 对于所有对象都通用的方法

### 第 8 条:覆盖 equals 时请遵守通用约定
覆盖 equals 方法看起来很简单,但是有很多覆盖方式会导致错误,并且后果非常严重。最容易避免这类问题的方法就是不覆盖 equals 方法,在这种情况下,类的每个实例都只能与它自身相等。如果满足了一下任何一个条件,这就正是所期望的结果:

- **类的每个实例本质上都是唯一的**。对于代表活动实体而不是值(`value`)的类来说确实如此,例如 Thread。Object 提供的 equals 实现对这些类来说正是正确的行为。

- **不关心类是否提供了“逻辑相等(`logical equality`)”的测试功能**。例如,java.util.Random 覆盖了 equals,以检查两个 Random 实例产生相同的随机数序列,但是设计者并不认为客户需要或者期望这样的功能。在这样的情况下,从 Object 继承得到的 equals 实现已经足够了。

- **超类已经覆盖了 equals,从超类继承过来的行为对于子类也是合适的**。例如,大多数 Set 实现都从 AbstractSet 继承 equals 实现,List 实现从 AbstractList 继承 equals 实现,Map 实现从 AbstractMap 继承实现。

- **类是私有的或是包级私有的,可以确定它的 equals 方法永远不会被调用**。在这种情况下,无疑是应该覆盖 equals 方法的,以防它被意外调用:

```java

@Override
public boolean equals(Object o) {
throw new AssertionError(); // Method is never called
}

```

那么什么时候应该覆盖 Object.equals 呢?如果类具有自己特有的“逻辑相等”概念(不同于对象等同的概念),而且超类还没有覆盖 equals 以实现期望的行为,这是我们就需要覆盖 equals 方法。

0 comments on commit 8af8def

Please sign in to comment.