跟C++(C++培訓(xùn) )一樣,Java中也有所謂的缺省構(gòu)造函數(shù),也就是沒(méi)有任何參數(shù)的構(gòu)造函數(shù)。Java的構(gòu)造函數(shù)有幾個(gè)基本的特性:
1)如果類中沒(méi)有顯式的制定構(gòu)造函數(shù)的時(shí)候,編譯器會(huì)自動(dòng)為該類添加一個(gè)缺省的構(gòu)造函數(shù);
2)如果類中有明確定義了一個(gè)以上的構(gòu)造函數(shù),編譯器則不會(huì)再為該類自動(dòng)添加任何構(gòu)造函數(shù);
3)編譯器在調(diào)用子類的每個(gè)構(gòu)造函數(shù)之前會(huì)先調(diào)用該父類的缺省構(gòu)造函數(shù)。
利用以上的特性,我們可以通過(guò)顯式定義一個(gè)非缺省構(gòu)造函數(shù),同時(shí)不顯式定義缺省構(gòu)造函數(shù)來(lái)使得該類不可被繼承。這個(gè)技巧意義不大,因?yàn)槲覀円部梢院?jiǎn)單地通 過(guò)final關(guān)鍵字來(lái)指明該類不可被繼承。但是反過(guò)來(lái)就是一個(gè)值得注意的地方,如果我們希望某類可以被繼承,那么在定義了非缺省構(gòu)造函數(shù)之后,要記得顯式 定義一個(gè)缺省構(gòu)造函數(shù)。這是一個(gè)編程初手容易犯的錯(cuò)誤,有一些初學(xué)者經(jīng)常會(huì)忘了在這種情況下顯式定義一個(gè)缺省構(gòu)造函數(shù)而導(dǎo)致該類不可被繼承。
通過(guò)將所有的構(gòu)造函數(shù)私有化,我們可以實(shí)現(xiàn)類的不可實(shí)例化。在一些工具類上我們經(jīng)常可以看到這種做法。我們也可以將某類定義為抽象類來(lái)實(shí)現(xiàn)其不可實(shí)例化。 但兩者比較起來(lái),前者會(huì)更優(yōu)雅,更明確,因?yàn)閷⒛愁惗x為抽象類會(huì)誤導(dǎo)用戶去繼承它。同時(shí),這個(gè)技巧也會(huì)使得該類不可被繼承,所以我們要根據(jù)實(shí)際情況來(lái)恰 當(dāng)選擇是用抽象類還是使用私有化構(gòu)造函數(shù)。
除了普通的構(gòu)造函數(shù)之外,我們有時(shí)也會(huì)通過(guò)一些工廠方法來(lái)創(chuàng)建對(duì)象,也就是Factory,F(xiàn)actory Method和Singleton等設(shè)計(jì)模式的應(yīng)用。在使用singleton模式的時(shí)候,我們要記得將構(gòu)造函數(shù)私有化,只有這樣才能真正保證該類具有唯一實(shí)例。此外,如果某個(gè)類同時(shí)提供了靜態(tài)工廠方法和構(gòu)造函數(shù),我們要優(yōu)先考慮前者,因?yàn)檫@樣可以減少對(duì)象的創(chuàng)建。我們還經(jīng)常使用對(duì)象池來(lái)創(chuàng)建對(duì)象。但是對(duì) 于對(duì)象池的使用必須慎重,在現(xiàn)有的JVM中,小對(duì)象的創(chuàng)建和回收是很快的,只有當(dāng)對(duì)象是重量級(jí)的時(shí)候,使用對(duì)象池才會(huì)有意義,否則反而會(huì)使得程序不夠清 晰,簡(jiǎn)潔。
在Java中有明確的構(gòu)造函數(shù),但是并不象C++,它沒(méi)有析構(gòu)函數(shù)。Java是通過(guò)finalizer( )方法來(lái)進(jìn)行對(duì)象的銷毀。而子類的finalizer方法并不會(huì)象前文所提的構(gòu)造函數(shù)一樣,主動(dòng)調(diào)用父類的相應(yīng)方法,因此一旦我們調(diào)用了finalizer方法,一定不要忘記先調(diào)用super.finalizer(), 這一點(diǎn)也是一些初手容易混淆的。在實(shí)際使用中,我們應(yīng)該盡量避免顯式的調(diào)用finalizer,因?yàn)樵谔摂M機(jī)規(guī)范中,對(duì)該方法的執(zhí)行并沒(méi)有明確的規(guī)定,不 同的JVM實(shí)現(xiàn)有自己不同的算法來(lái)安排finalizer,因此我們不能保證該方法能及時(shí)調(diào)用,甚至無(wú)法保證執(zhí)行。