Skip to content

Commit

Permalink
Merge pull request #5 from joyang1/master
Browse files Browse the repository at this point in the history
Add Article 4 for Effective Java
  • Loading branch information
yanglbme authored Jul 1, 2019
2 parents 19808fc + 6f5c50c commit a75e4fd
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion docs/effective-java.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,4 +221,25 @@ public enum Singleton {
}
```

这种方法更加简洁,无偿提供了序列化机制,绝对防止多次实例化,是实现 Singleton 的最佳方式。
这种方法更加简洁,无偿提供了序列化机制,绝对防止多次实例化,是实现 Singleton 的最佳方式。

### 第 4 条:通过私有构造器强化不可实例化的能力
我们在项目开发过程中,有时候肯定会遇到一些工具类,我们不希望它们被实例化,因为它们的方法可能都被 `static` 来修饰,所以实例对它们没有任何的意义;然而我们在编码的过程中,可能往往对一些工具类的编写都没有注意,没有去写构造方法,这时候,在缺少显式的构造器的情况下,编译器会提供一个共有的、无参的缺省构造器(`default constructor`)。对于用户而言,这个构造器和其它的构造器没有任何区别。所以在一些已发行的 API 里面我们经常会看到一些被无意识实例化的类。

**企图通过讲类做成抽象类来强制该类不可被实例化,这是行不通的。** 因为抽象类可以被子类化,子类也可以被实例化。同时定义为抽象类,还会误导用户,以为这种类是专门为了继承而设计的。那怎样才可以确保类不被实例化呢,因为只有当类不包含显示的构造器时,编译器才会生成缺省的构造器,所以我们只要给这个类构建私有的构造器,它就不会被实例化了:

```java
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}

... // Remainder omitted
}
```

如上,由于显示的构造器是私有的,则不会在类的外部被实例化。 AssertionError 不是必须的,但是这样写,可以避免在类的内部调用构造器。它保证该类在任何情况下都不会被实例化。

**注意** 这种用法也有副作用,它使得一个类不能被子类化。因为所有的构造器都必须显式或隐式地调用超类(superclass)构造器,在上面这种情况下,子类就没有可访问的超类构造器去调用了。

0 comments on commit a75e4fd

Please sign in to comment.