1. 程式人生 > >Effective Java 第三版讀書筆記——條款3:使用私有構造器來強制實現不可例項化

Effective Java 第三版讀書筆記——條款3:使用私有構造器來強制實現不可例項化

偶爾你會想寫一個類,這個類只是一組靜態方法和靜態屬性。 這樣的類獲得了不好的名聲,因為有些人濫用這些類而避免以面向物件的方式思考,但是它們有時候確實有實際的用處:

  • 它們可以被用來聚集一組建立在基礎型別或陣列之上的相關方法,例如 java.lang.Mathjava.util.Arrays
  • 它們也可以用於一組靜態方法,用於實現某個介面的物件,例如 java.util.Collections
  • 最後,這樣的類可以用於 final 類上的一組方法,因為不能將它們放在子類中。

這樣的實用類(utility classes)是不能被設計為可例項化類的:一個例項是沒有意義的。然而,以下兩種實現不可例項化類的方法都是錯誤

的:

  • 不提供顯示構造器。在沒有顯式構造器的情況下,編譯器提供了一個公共的、無參的預設構造器。對於使用者來說,該構造方法與其他構造方法沒有什麼區別。
  • 建立抽象類。抽象類可以被子類化,子類可以被例項化。此外,它誤導使用者認為該類是為繼承而設計的(條款 19)。

不過,有一個簡單的方法來確保不可例項化。只有當類不包含顯式構造器時,才會生成一個預設構造器,因此可以通過包含一個私有構造器來實現類的不可例項化:

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

因為顯式構造器是私有的,所以在該類之外是不可訪問的。這個習慣用法有點違反直覺,好像構造器就是設計成不能呼叫的一樣。因此,添加註釋是種明智的做法。

這種方法還有另一個作用——阻止了類的繼承。所有的構造器都必須顯式或隱式地呼叫父類的構造器,而繼承該類的子類卻沒有可訪問的父類構造器來呼叫。