C++(C++培訓(xùn) 一樣,Java中也有所謂的缺省構(gòu)造函數(shù),也就是沒有任何參數(shù)的構(gòu)造函數(shù)。Java的構(gòu)造函數(shù)有幾個基本的特性:

  1)如果類中沒有顯式的制定構(gòu)造函數(shù)的時候,編譯器會自動為該類添加一個缺省的構(gòu)造函數(shù);

  2)如果類中有明確定義了一個以上的構(gòu)造函數(shù),編譯器則不會再為該類自動添加任何構(gòu)造函數(shù);

  3)編譯器在調(diào)用子類的每個構(gòu)造函數(shù)之前會先調(diào)用該父類的缺省構(gòu)造函數(shù)。

  利用以上的特性,我們可以通過顯式定義一個非缺省構(gòu)造函數(shù),同時不顯式定義缺省構(gòu)造函數(shù)來使得該類不可被繼承。這個技巧意義不大,因為我們也可以簡單地通 過final關(guān)鍵字來指明該類不可被繼承。但是反過來就是一個值得注意的地方,如果我們希望某類可以被繼承,那么在定義了非缺省構(gòu)造函數(shù)之后,要記得顯式 定義一個缺省構(gòu)造函數(shù)。這是一個編程初手容易犯的錯誤,有一些初學(xué)者經(jīng)常會忘了在這種情況下顯式定義一個缺省構(gòu)造函數(shù)而導(dǎo)致該類不可被繼承。

  通過將所有的構(gòu)造函數(shù)私有化,我們可以實現(xiàn)類的不可實例化。在一些工具類上我們經(jīng)常可以看到這種做法。我們也可以將某類定義為抽象類來實現(xiàn)其不可實例化。 但兩者比較起來,前者會更優(yōu)雅,更明確,因為將某類定義為抽象類會誤導(dǎo)用戶去繼承它。同時,這個技巧也會使得該類不可被繼承,所以我們要根據(jù)實際情況來恰 當(dāng)選擇是用抽象類還是使用私有化構(gòu)造函數(shù)。

  除了普通的構(gòu)造函數(shù)之外,我們有時也會通過一些工廠方法來創(chuàng)建對象,也就是Factory,F(xiàn)actory Method和Singleton等設(shè)計模式的應(yīng)用。在使用singleton模式的時候,我們要記得將構(gòu)造函數(shù)私有化,只有這樣才能真正保證該類具有唯一實例。此外,如果某個類同時提供了靜態(tài)工廠方法和構(gòu)造函數(shù),我們要優(yōu)先考慮前者,因為這樣可以減少對象的創(chuàng)建。我們還經(jīng)常使用對象池來創(chuàng)建對象。但是對 于對象池的使用必須慎重,在現(xiàn)有的JVM中,小對象的創(chuàng)建和回收是很快的,只有當(dāng)對象是重量級的時候,使用對象池才會有意義,否則反而會使得程序不夠清 晰,簡潔。

  在Java中有明確的構(gòu)造函數(shù),但是并不象C++,它沒有析構(gòu)函數(shù)。Java是通過finalizer( )方法來進(jìn)行對象的銷毀。而子類的finalizer方法并不會象前文所提的構(gòu)造函數(shù)一樣,主動調(diào)用父類的相應(yīng)方法,因此一旦我們調(diào)用了finalizer方法,一定不要忘記先調(diào)用super.finalizer(), 這一點也是一些初手容易混淆的。在實際使用中,我們應(yīng)該盡量避免顯式的調(diào)用finalizer,因為在虛擬機(jī)規(guī)范中,對該方法的執(zhí)行并沒有明確的規(guī)定,不 同的JVM實現(xiàn)有自己不同的算法來安排finalizer,因此我們不能保證該方法能及時調(diào)用,甚至無法保證執(zhí)行。