Effective Java 讀書筆記(1)

創(chuàng)建和銷毀對(duì)象


第一條:考慮用靜態(tài)工廠方法代替構(gòu)造器

當(dāng)該類需要返回不同的實(shí)例(子類實(shí)例),或者唯一一個(gè)實(shí)例(單例)時(shí),應(yīng)考慮用靜態(tài)工廠方法代替構(gòu)造器。
靜態(tài)工廠方法的一些慣用名稱:

  • valueOf 返回的實(shí)例與參數(shù)有相同的值,相當(dāng)于類型轉(zhuǎn)換
  • of valueOf的簡(jiǎn)化
  • getInstance 返回的實(shí)例是通過(guò)參數(shù)類描述的,但一般不具有與參數(shù)同樣的值。對(duì)于Singleton來(lái)說(shuō),無(wú)參數(shù),返回唯一一個(gè)實(shí)例。
  • newInstance 類似于getInstance,但每次返回新的實(shí)例
  • getType 在工廠方法處于不同的類時(shí)使用,Type指返回類型的類型
  • newType 同上

第二條:遇到多個(gè)構(gòu)造器參數(shù)時(shí)要考慮用構(gòu)建器

當(dāng)創(chuàng)建對(duì)象面臨多個(gè)可選參數(shù)時(shí)(即,構(gòu)造器有多個(gè)可選的參數(shù)),有以下三種方案:

  • 重疊構(gòu)造器模式
    根據(jù)參數(shù)的不同組合,編寫多個(gè)簽名不同的構(gòu)造器或靜態(tài)工廠方法。優(yōu)點(diǎn):線程安全,參數(shù)組合少時(shí)簡(jiǎn)單;缺點(diǎn):當(dāng)參數(shù)量很大,且其組合很多時(shí),代碼編寫麻煩且可讀性差
  • JavaBean模式
    調(diào)用一個(gè)構(gòu)造器類創(chuàng)建對(duì)象并設(shè)置必要的參數(shù),再通過(guò)setter方法類設(shè)置每個(gè)可選參數(shù)。優(yōu)點(diǎn):實(shí)例簡(jiǎn)單,代碼簡(jiǎn)潔,可擴(kuò)展性強(qiáng)。缺點(diǎn):構(gòu)造過(guò)程被分為多個(gè)調(diào)用方法,難以保證一致性,(多線程)易出錯(cuò)難調(diào)試;無(wú)法實(shí)例化一個(gè)不可變對(duì)象(致命)
  • Builder模式
    不直接生成想要的對(duì)象,而是先用必要的參數(shù)實(shí)例化一個(gè)builder,再用setter方法設(shè)置每個(gè)可選參數(shù),最后調(diào)用無(wú)參的build方法來(lái)生成不可變的對(duì)象。既能保證重疊構(gòu)造器模式的安全性,也能保證像JavaBean一樣簡(jiǎn)單可讀

第三條:用私有構(gòu)造器或者枚舉類型強(qiáng)化Singleton屬性

實(shí)現(xiàn)Singleton有以下三種方法:

  • 將構(gòu)造器私有化,將實(shí)例設(shè)為公有的靜態(tài)final成員。私有構(gòu)造器只被調(diào)用一次,用來(lái)實(shí)例化單例:
public class FirstSingleton {
    public String message;
    public static final FirstSingleton INSTANCE = new FirstSingleton();

    private FirstSingleton(){
        message = "Hello World! First Singleton!";
    }
}

由于缺少公有的或者受保護(hù)的構(gòu)造器,所以保證了單例的全局唯一性。

注意:享有特權(quán)的客戶端可以借助AccessibleObject.setAccessibe方法,通過(guò)反射機(jī)制調(diào)用私有構(gòu)造器。如果需要抵御這種攻擊,可以修改私有構(gòu)造器,使其在構(gòu)造第二個(gè)實(shí)例時(shí)拋出異常。

  • 公有的成員是個(gè)靜態(tài)工廠方法:
public class SecondSingleton {
    public String message;
    private static final SecondSingleton INSTANCE  = new SecondSingleton();
    private SecondSingleton(){
        message = "Hello World! Second Singleton!";
    }
    public static SecondSingleton getInstance(){
        return INSTANCE;
    }
}

對(duì)于靜態(tài)方法getInstance的所有調(diào)用,都會(huì)返回同一個(gè)對(duì)象引用(上述注意依然使用)。
公有域方法的主要好處在于,組成類的成員的聲明很清楚第表明了這個(gè)類是一個(gè)Singleton:公有的靜態(tài)域是final的,所以該域?qū)⒖偸前嗤膶?duì)象引用。

對(duì)于以上兩種方法,在序列化時(shí),僅僅在聲明中加上implements Serializable是不夠的。為了維護(hù)并保證Singleton,必須聲明所有的實(shí)例域都是瞬時(shí)的(transient)的,并提供一個(gè)readResove實(shí)例。否則,每次反序列化一個(gè)實(shí)例時(shí),都會(huì)創(chuàng)建一個(gè)新的實(shí)例:

    private Object readResolve(){
        return INSTANCE;
    }
  • 編寫一個(gè)包含單個(gè)元素的枚舉類型:
    public enum ThirdSingleton {
    INSTANCE;
    public String message = "Hello World! Third Singleton!";
}

這種方法在功能上與公有域方法相近,但是其更加簡(jiǎn)潔,無(wú)償?shù)靥峁┝诵蛄谢瘷C(jī)制,絕對(duì)防止多次實(shí)例化,即使是在面對(duì)復(fù)雜的序列化或者反射攻擊時(shí)。單元素的枚舉類型已經(jīng)成為實(shí)現(xiàn)Singleton的最佳方法。


第四條:通過(guò)私有化構(gòu)造器強(qiáng)化不可實(shí)例的能力

有時(shí)候,我們需要編寫只包含靜態(tài)方法和靜態(tài)域的類。這些工具類不希望被實(shí)例化,實(shí)例對(duì)它沒(méi)有任何意義。這個(gè)時(shí)候,我們需要私有化構(gòu)造器,防止其在無(wú)意間被實(shí)例化。


第五條:避免創(chuàng)建不必要的對(duì)象

一般來(lái)說(shuō),最好能重用對(duì)象而不是每次需要 的時(shí)候就創(chuàng)建一個(gè)相同功能的新對(duì)象。

  • 重用不可變對(duì)象:如果對(duì)象是不可變的,它就始終可以被重用(單例模式、String對(duì)象池)
  • 重用已知不會(huì)被修改的可變對(duì)象。創(chuàng)建某些對(duì)象的成本是十分昂貴的,且其在創(chuàng)建之后,其值一般不會(huì)改變,此時(shí)我們可以考慮重用這個(gè)對(duì)象已減少創(chuàng)建成本。
  • 使用適配器(適配器是指這樣一個(gè)對(duì)象:它把功能委托給一個(gè)后備對(duì)象,從而為后備對(duì)象提供一個(gè)可以替代的接口)。如Map類的KeySet方法,它返回一個(gè)Set對(duì)象。對(duì)于一個(gè)Map而言,它的key是可變的,但是keySet對(duì)象是唯一的,只是其內(nèi)容會(huì)發(fā)生變化。
  • 優(yōu)先使用基本類型而不是自動(dòng)裝箱基本類型,當(dāng)心無(wú)意識(shí)的自動(dòng)裝箱。

第六條:消除過(guò)期的對(duì)象引用

在支持垃圾回收的語(yǔ)言中,內(nèi)存泄漏是很隱蔽的,稱之為“無(wú)意識(shí)的對(duì)象保持(unintentional object retention)“更為恰當(dāng)。如果一個(gè)對(duì)象被無(wú)意識(shí)保留起來(lái),那么垃圾回收機(jī)制不僅不會(huì)去處理這個(gè)對(duì)象,而且不會(huì)處理這個(gè)對(duì)象所引用的所有其他對(duì)象,久而久之會(huì)對(duì)性能造成潛在的重大影響。

這種問(wèn)題一般出現(xiàn)在堆、棧、數(shù)組、鏈表等數(shù)據(jù)結(jié)果在pop對(duì)象時(shí)沒(méi)有消除引用,如size--;
這種問(wèn)題的解決方法很簡(jiǎn)單,一旦對(duì)象過(guò)期,清空這些引用即可stack[size--] = null;

內(nèi)存泄漏的常見(jiàn)來(lái)源:

  • 類自己管理內(nèi)存。當(dāng)我們需要寫自己管理內(nèi)存 的類時(shí),如手動(dòng)實(shí)現(xiàn)一個(gè)stack,應(yīng)謹(jǐn)記一旦元素不需要用到,要立即釋放(消除引用),以便垃圾回收機(jī)制能及時(shí)回收。
  • 緩存。緩存中的對(duì)象極易被遺忘。-> 使用WeakHashMap代表緩存
  • 監(jiān)聽(tīng)器及其他回調(diào)。如果你實(shí)現(xiàn)了一個(gè)API,客戶端在這個(gè)API中注冊(cè)回調(diào),卻沒(méi)有顯式取消注冊(cè),那么除非你采取某些動(dòng)作,否則它們就會(huì)被積聚。確保回調(diào)立即被當(dāng)做立即回收的最佳方法是只保存它們的弱引用。

第七條:避免使用終結(jié)方法

終結(jié)方法(finalizer)通常是不可預(yù)測(cè)的,也是很危險(xiǎn)的。
終結(jié)方法通常在垃圾回收機(jī)制回收對(duì)象時(shí)負(fù)責(zé)執(zhí)行,其執(zhí)行時(shí)間取決于jvm設(shè)計(jì)、配置以及程序執(zhí)行過(guò)程。而且,java規(guī)范并不保證終結(jié)方法一定會(huì)被執(zhí)行。還有一點(diǎn),使用終結(jié)方法會(huì)帶來(lái)嚴(yán)重的性能損耗。
若一個(gè)對(duì)象需要在其終結(jié)時(shí)進(jìn)行某些動(dòng)作,可以考慮使用顯式終結(jié)動(dòng)作,并要求所有客戶端在結(jié)束該實(shí)例時(shí)調(diào)用該方法,例如InputStream接口的close方法
終結(jié)方法的合法用途:

  • 充當(dāng)顯式終結(jié)方法的“安全網(wǎng)(safety net)。
  • 終結(jié)非關(guān)鍵的本地資源(一般指本地對(duì)等體native peer),即本地對(duì)象。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,606評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,044評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,826評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,227評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,447評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,807評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,001評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評(píng)論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,243評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,667評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,930評(píng)論 1 287
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,709評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,996評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容