《Effective Java》第一章——創(chuàng)建和銷毀對象

內(nèi)容摘引自《Effective Java》(第二版者吁,機械工業(yè)出版社)

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

這樣做的好處

  • 靜態(tài)工廠方法有名稱劈愚,能夠讓人更易閱讀浴滴,防止在開發(fā)過程中忘記應該使用哪個構(gòu)造器的情況
  • 不必每次調(diào)用的時候都創(chuàng)建一個新的對象彻磁,當需要不可變類(實例內(nèi)容不可改變的類)的時候可以使用預先構(gòu)建好的實例,從而避免了重復創(chuàng)建對象蓝牲,提升了性能
  • 它可以返回原返回類型的任何子類型對象趟脂,從而提高的靈活性
  • 在創(chuàng)建參數(shù)化類型實例的時候泰讽,它能使得代碼變得簡潔

靜態(tài)工廠方法的缺點

  • 類如果不含有公有的或者受保護的構(gòu)造器例衍,就不能被子類化
  • 它與其他的靜態(tài)方法實際上并沒有任何區(qū)別,他可能不能像API文檔那樣直接明確標識出來

靜態(tài)方法的慣用名稱

  • valueOf——類型轉(zhuǎn)換已卸,返回與它參數(shù)相同的值
  • of——是valueOf的簡潔替代
  • getInstance——返回的實例時通過方法的參數(shù)來描述的佛玄,但不能夠說與參數(shù)有相同的值。對于Singleton(單例)來說累澡,改方法沒有參數(shù)梦抢,并返回唯一的實例
  • newInstance——類似于getInstance,但是newInstance能夠確保返回的每一個實例都與其他的不同
  • getType——像getInstance一樣愧哟,表示工廠方法返回的數(shù)據(jù)類型奥吩,主要早不同的類的時候使用。
  • newType——像newInstance一樣蕊梧,但是在工廠方法處于不同的類中的時候使用霞赫。Type表示工廠方法返回的對象類型

服務提供者框架

定于:多個服務提供者實現(xiàn)一個服務,系統(tǒng)為服務提供者的客戶端提供多個實現(xiàn)肥矢,并把他們從多個實現(xiàn)中解耦出來端衰。
這是一個靜態(tài)工廠方法的實例
服務提供者框架包含四個部分

  • 服務接口(Service Interface),這是提供者實現(xiàn)的
  • 提供者注冊API(Provider Registation API),這是系統(tǒng)用來注冊實現(xiàn)的旅东,讓客戶端訪問他們的灭抑。
  • 服務訪問API(Service Access API),是客戶端用來獲取服務的實例的抵代。它一般允許但是不要求客戶端指定某種選擇提供者的條件腾节,如果客戶端沒有這樣的指定,那么一般會返回給一個默認的實例荤牍。它是一個“靈活的靜態(tài)工廠”禀倔,它構(gòu)成了服務提供者框架的基礎
  • 服務提供者接口(Service Provider Interface),這是一個可選的参淫,這些提供者負責創(chuàng)建其服務實現(xiàn)的實例救湖。如果沒有提供實例那么實現(xiàn)就按照類名進行注冊,并通過反射方式進行實例化涎才。

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

當一個實體有多個屬性鞋既,而有的屬性是非必需的那么在創(chuàng)建實例的時候可能會有多個構(gòu)造函數(shù)可供選擇,舉例來說如下

package com.myclass;

public class OldPerson {
    private int age;
    private String name;
    private double weight;
    private String hobby;
    public OldPerson(int age, String name, double weight, String hobby) {
        // TODO Auto-generated constructor stub
        this.age = age;
        this.name = name;
        this.weight = weight;
        this.hobby = hobby;
    }
    
    //當weight和hobby不是必須的時候耍铜,我們在創(chuàng)建OldPerson就需要這樣
    public OldPerson(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

如果有很多個參數(shù)那么構(gòu)造函數(shù)就可能會有很多邑闺,可能會在使用的時候不小心顛倒了兩個參數(shù)或者別的小問題,所以這種重疊構(gòu)造器模式是可以的棕兼,但是當有許多參數(shù)的時候陡舅,客戶端代碼會很難編寫,并且難以閱讀伴挚。

更好地方法

package com.myclass;

public class Person {
    private int age;
    private String name;
    private double weight;
    private String hobby;
    
    public static class Builder {
        //必填參數(shù)
        private String name;
        
        //選填參數(shù)靶衍,設置默認值
        private int age = 0;
        private double weight = 0.0;
        private String hobby = "寫bug";
        
        //設置必填參數(shù)
        public Builder (String name) {
            this.name = name;
        }
        
        //設置非必填參數(shù)
        public Builder age(int age) {
            this.age = age;
            return this;
        }
        public Builder weight(int weight) {
            this.weight = weight;
            return this;
        }
        public Builder hobby(String hobby) {
            this.hobby = hobby;
            return this;
        }
        
        public Person build() {
            return new Person(this);
        }
    }
    
    public Person(Builder builder) {
        // TODO Auto-generated constructor stub
        age = builder.age;
        name = builder.name;
        weight = builder.weight;
        hobby = builder.hobby;
    }
}

這樣當我們使用的時候只需要這樣

     Person person = new Person.Builder("Slience愛學習").weight(120).hobby("看書").build();

就可以了(雖然我用的比較多的是JavaBean模式)

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

(這一條沒怎看懂)

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

我們知道當類中沒有顯式的構(gòu)造器的時候,系統(tǒng)會自動生成一個缺省的構(gòu)造器茎芋,當我們想要讓一個類不能被實例的時候(比如說一些工具類)颅眶,我們可以自己寫一個構(gòu)造函數(shù),并把構(gòu)造函數(shù)設置為私有的田弥,這樣就不會創(chuàng)建這個實例了涛酗,舉例來說就是

package com.myclass;

public class MyClass {
    public static String say() {
        return "Hello World";
    }
    private MyClass() {
        // TODO Auto-generated constructor stub
    }
}

這樣我們就創(chuàng)建不了MyClass實例,而只能使用它的say方法了偷厦。

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

String str = "Hello World";
String str2 = new String("Hello World");

str相對于str2效率要高商叹,因為在創(chuàng)建對象的時候"Hello World"已經(jīng)是一個對象了,沒有必要在用一層new String包裹起來再創(chuàng)建一個對象只泼。
再舉一個例子

        long start = System.currentTimeMillis();
        long sum = 0L;
        for(long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);
        System.out.println("耗時:" + (System.currentTimeMillis() - start));

        long start = System.currentTimeMillis();
        Long sum = 0L;
        for(long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);
        System.out.println("耗時:" + (System.currentTimeMillis() - start));

兩者的執(zhí)行耗時是不一樣的剖笙,后者使用Long的耗時更大,因為要將i轉(zhuǎn)成Long給sum加上辜妓,這意味著程序創(chuàng)造了不必要的很多個Long實例枯途,造成了更多的耗時忌怎。

第六條:消除過期的對象引用

(原書是一個棧增長再減少的例子),減少掉的元素可能不會被垃圾回收酪夷,在極端情況下可能會造成內(nèi)存泄漏榴啸。這是因為棧內(nèi)部維護者這些對象的過期應用。
過期應用是指永遠也不會被解除的引用晚岭。
解決這種問題的辦法也很簡單鸥印,那就是當對象引用過期的時候清空這些引用就可以了。

        String[] strs = {"星期一","星期二","星期三","星期四"};
        //如果要取出最后一個坦报,應該這樣
        String str = strs[strs.length-1];
        strs[strs.length-1] = null;
        System.out.println(str);

這樣做的好處是當你不小心錯誤的解除引用库说,程序會報空指針異常而不是悄咪咪的運行下去。

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

終結(jié)方法finalizer的線程優(yōu)先級比其他應用程序的線程要低片择,如果要使用finalizer去結(jié)束一個一個比較有限的資源潜的,比如說打開很多個文件的描述符(原文如此,可能是指explorer這樣的東東吧)字管,當你想要關掉它的時候再打開新的啰挪,因為優(yōu)先級低所以可能先去打開新的然后舊的沒有去關掉,關掉的速度比打開的速度低造成了資源的占用嘲叔。比較常見的終結(jié)方法有InputStream亡呵、java.sql.Connention中的colse方法。
顯示終結(jié)方法通常與try-finally結(jié)合起來使用硫戈,確保及時終止锰什。
終結(jié)方法前使用try-finally顯示終結(jié)的好處

  • 可以充當終結(jié)方法的“安全網(wǎng)”,這樣就算終結(jié)方法沒有按時關閉也可以有所動作以便做一些補救丁逝。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汁胆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子果港,更是在濱河造成了極大的恐慌沦泌,老刑警劉巖糊昙,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辛掠,死亡現(xiàn)場離奇詭異,居然都是意外死亡释牺,警方通過查閱死者的電腦和手機萝衩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來没咙,“玉大人猩谊,你說我怎么就攤上這事〖栏眨” “怎么了牌捷?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵墙牌,是天一觀的道長。 經(jīng)常有香客問我暗甥,道長喜滨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任撤防,我火速辦了婚禮虽风,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寄月。我一直安慰自己辜膝,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布漾肮。 她就那樣靜靜地躺著厂抖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪克懊。 梳的紋絲不亂的頭發(fā)上验游,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音保檐,去河邊找鬼耕蝉。 笑死,一個胖子當著我的面吹牛夜只,可吹牛的內(nèi)容都是我干的垒在。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扔亥,長吁一口氣:“原來是場噩夢啊……” “哼场躯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起旅挤,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤踢关,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后粘茄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體签舞,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年柒瓣,在試婚紗的時候發(fā)現(xiàn)自己被綠了儒搭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡芙贫,死狀恐怖搂鲫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情磺平,我是刑警寧澤魂仍,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布拐辽,位于F島的核電站,受9級特大地震影響擦酌,放射性物質(zhì)發(fā)生泄漏薛训。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一仑氛、第九天 我趴在偏房一處隱蔽的房頂上張望乙埃。 院中可真熱鬧,春花似錦锯岖、人聲如沸介袜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遇伞。三九已至,卻和暖如春捶牢,著一層夾襖步出監(jiān)牢的瞬間鸠珠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工秋麸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渐排,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓灸蟆,卻偏偏與公主長得像驯耻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子炒考,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

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