本章的主題是創建和銷毀對象:何時以及如何創建對象,何時以及如何避免創建對象,如何確保它們能夠適時地銷毀,以及如何管理對象銷毀之前必須進行的各種清理動作。
[toc]
有時候,你可能需要編寫只包含靜態方法和靜態域的類。雖然這些類名聲很不好,因為有些人在面向對象的語言中濫用這樣的類來編寫過程化的程序。盡管如此,它們也確實有它們特有的用處。我們可以利用這種類,以 java.lang.Math 或者 java.util.Arrays 的方式,把基本類型的值或者數組類型上的相關方法組織起來。我們也可以通過 java.util.Collections 的方式,把實現特定接口的對象上的靜態方法(包括靜態方法,見第1條)組織起來。最后還可以利用這種類把 final 類上的方法組織起來,以取代擴展該類的做法。
這樣的工具類(utility class)不希望被實例化,實例對它沒有任何意義。然而在缺少顯石子構造器的情況下,編譯器會自動提供一個公有的、無參的缺省構造器(default constructor)。對于用戶而言,這個構造器與其他構造器沒有任何區別。在已經發行的API中常??梢钥吹揭恍┍粺o意識地實例化的類。
企圖通過將類做成抽象類來強制該類不可被實例化,這是行不通的
該類可以被子類化,并且該子類也可以被實例化。這樣可能會誤導用戶,以為這種類是專門為了繼承而設計的(見 17 條)。
而我們只需要讓這個類只包含私有構造器,它就不能被實例化了:
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
... // Remainder omitted
}
由于顯式的構造器是私有的,所以不可以在該類的外部訪問它。AssertionError 不是必須的,它可以避免不小心在類的內部調用構造器,防止該類被實例化,這種習慣用法有點違背直覺,好像構造器就是專門設計成不能被調用一樣。所以最好加上一條注釋。如上所示。
副作用:
- 使得一個類不能被子類化。
所有的構造器都必須顯式或隱式地調用超類(superclass)構造器,在這種情況下,子類就沒有可訪問的超類構造器可調用了。