[Effective Java] (05)避免創(chuàng)建不必要的對象

一般來說雕蔽,最好能夠重用對象而不是在每次需要的時(shí)候就創(chuàng)建一個(gè)相同功能的新對象舅踪。

  • 如:反面例子
String name = new String("QyQiaoo");

其中:上述語句每次被執(zhí)行的時(shí)候都創(chuàng)建一個(gè)新的String實(shí)例霍弹,但是這些創(chuàng)建對象的動(dòng)作全都是不必要的侯繁。創(chuàng)建名為name的String實(shí)例時(shí)组贺,傳遞給String的構(gòu)造器的參數(shù)("QyQiaoo")本身就是一個(gè)String實(shí)例,功能方面等同于構(gòu)造器創(chuàng)建的所有對象叠必。如果這種用法是在一個(gè)循環(huán)中荚孵,或者在一個(gè)被頻繁調(diào)用的方法中,就會(huì)創(chuàng)建成千上萬個(gè)不必要的String實(shí)例纬朝。該井版如下:

String name = "QyQiaoo";
1. 同時(shí)提供了靜態(tài)工廠方法和構(gòu)造器的不可變類

對于同時(shí)提供了靜態(tài)工廠方法和構(gòu)造器的不可變類收叶,通常可以使用靜態(tài)工廠方法而不是構(gòu)造器共苛,以免創(chuàng)建不必要的對象判没。構(gòu)造器在每次被調(diào)用的時(shí)候都會(huì)創(chuàng)建一個(gè)新的對象,而靜態(tài)工廠方法則從來沒有要求這樣做隅茎。

  • 如:靜態(tài)工廠方法Boolean.valueOf(String)幾乎總是優(yōu)先于構(gòu)造器Boolean(String);
2. 重用已知不會(huì)被修改的可變對象

除了重用不可變的對象之外澄峰,也可以重用那些已知不會(huì)修改的可變對象。
如下例子辟犀,判斷baby是否在出生大爆炸時(shí)期出生:

public class Person {
    private Date birthDate;
    
    //Donnot do this
    public boolean isBabyBoomer() {
        // Unnecessary allocation of expensive object
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        calendar.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
        Date boomStart = calendar.getTime();
        calendar.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
        Date boomEnd = calendar.getTime();
        
        return birthDate.compareTo(boomStart) >= 0 &&
                birthDate.compareTo(boomEnd) < 0;
    }
}

注:isBabyBommer方法每次被調(diào)用的時(shí)候俏竞,都會(huì)創(chuàng)建一個(gè)Calendar、TimeZone和Date實(shí)例一次堂竟,這并不是必須的魂毁,下面我們采用靜態(tài)的初始化器,可以避免這種效率低下的情況跃捣。

public class Person {
    private Date birthDate;
    
    private static final Date BOOM_START;
    private static final Date BOOM_END;
    
    static {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        calendar.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
        BOOM_START = calendar.getTime();
        calendar.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
        BOOM_END = calendar.getTime();
    }
    
    public boolean isBabyBoomer() { 
        return birthDate.compareTo(BOOM_START) >= 0 &&
                birthDate.compareTo(BOOM_END) < 0;
    }
}

改進(jìn)后的Person類只在初始化的時(shí)候創(chuàng)建Calendar漱牵、TimeZone和Date實(shí)例,而不是每次調(diào)用isBabyBommer的時(shí)候都會(huì)創(chuàng)建這些實(shí)例疚漆,該方法能夠顯著的提高性能酣胀。

3. 適配器情形

適配器情形:有時(shí)也叫作視圖(View)刁赦,它把功能委托給一個(gè)后備對象(backing object),從而為后備對象提供一個(gè)可以替代的接口闻镶。由于適配器除了后備對象之外甚脉,沒有其他狀態(tài)信息,所以針對某個(gè)給定對象的特定適配器而言铆农,它不需要?jiǎng)?chuàng)建多個(gè)適配器實(shí)例牺氨。

  • 如:Map接口的keySet方法返回該Map對象的Set視圖,其中包含該Map中所有的鍵(key)墩剖。粗看起來猴凹,好像每次調(diào)用keySet都應(yīng)該創(chuàng)建一個(gè)新的Set實(shí)例,但是岭皂,對于一個(gè)給定的Map對象郊霎,實(shí)際上每次調(diào)用keySet都返回同樣的Set實(shí)例。雖然被返回的Set實(shí)例一般是可改變的爷绘,但是所有返回的對象在功能上是等同的:當(dāng)其中一個(gè)返回對象發(fā)生變化的時(shí)候书劝,所有其他返回對象也要發(fā)生變化,因?yàn)樗鼈兪怯赏粋€(gè)Map實(shí)例支撐的土至。雖然創(chuàng)建keySet視圖對象的多個(gè)實(shí)例并無害處购对,卻也是沒有必要的。&(以后慢慢體會(huì)陶因,未完待續(xù)···)&
4. 自動(dòng)裝箱(創(chuàng)建多余對象的新方法)

基本類型與裝箱基本類型的會(huì)用骡苞,會(huì)創(chuàng)建多余的對象。
如下代碼:

public static void main(String[] args) {
    
    Long sum = 0L;
    for(long i = 0; i < Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);    
}

注:在每次執(zhí)行sum += i時(shí)會(huì)構(gòu)造一個(gè)實(shí)例楷扬,因此在我們無意中創(chuàng)建了2^31個(gè)多余的實(shí)例烙如。

要優(yōu)先使用基本類型而不是裝箱基本類型,更要當(dāng)心無意識的自動(dòng)裝箱毅否。

5. 結(jié)語
  • 不要錯(cuò)誤地認(rèn)為"創(chuàng)建對象的代價(jià)非常昂貴,我們應(yīng)該盡可能地避免創(chuàng)建對象"蝇刀。相反螟加,由于小對象的構(gòu)造器只做很少量的顯示工作,所以小對象的創(chuàng)建和回收動(dòng)作是非常廉價(jià)的吞琐,特別是在現(xiàn)代的JVM實(shí)現(xiàn)上更是如此捆探。通過創(chuàng)建附加的對象,提升程序的清晰性站粟、簡潔性和功能性黍图,這通常是件好事。

  • 反之奴烙,通過維護(hù)自己的對象池(Object pool)來避免創(chuàng)建對象并不是一種好的做法助被,除非池中的對象是非常重量級的剖张。真正正確使用對象池的典型對象示例就是數(shù)據(jù)庫連接池。建立數(shù)據(jù)庫連接的代價(jià)是非常昂貴的揩环,因此重用這些對象非常有意義搔弄。而如今的JVM(Java虛擬機(jī))具有高度優(yōu)化的垃圾回收器,如果是輕量的對象池可能還不如垃圾回收器的性能丰滑。

  • 當(dāng)你應(yīng)該重用現(xiàn)有對象的時(shí)候顾犹,請不要?jiǎng)?chuàng)建新的對象

  • 當(dāng)你應(yīng)該創(chuàng)建新對象的時(shí)候,請不要重用現(xiàn)有的對象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末褒墨,一起剝皮案震驚了整個(gè)濱河市炫刷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌郁妈,老刑警劉巖浑玛,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異圃庭,居然都是意外死亡锄奢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門剧腻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拘央,“玉大人,你說我怎么就攤上這事书在』椅埃” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵儒旬,是天一觀的道長栏账。 經(jīng)常有香客問我,道長栈源,這世上最難降的妖魔是什么挡爵? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮甚垦,結(jié)果婚禮上茶鹃,老公的妹妹穿的比我還像新娘。我一直安慰自己艰亮,他們只是感情好闭翩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迄埃,像睡著了一般疗韵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侄非,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天蕉汪,我揣著相機(jī)與錄音流译,去河邊找鬼。 笑死肤无,一個(gè)胖子當(dāng)著我的面吹牛先蒋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宛渐,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼竞漾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窥翩?” 一聲冷哼從身側(cè)響起业岁,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寇蚊,沒想到半個(gè)月后笔时,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仗岸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年允耿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扒怖。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡较锡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盗痒,到底是詐尸還是另有隱情蚂蕴,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布俯邓,位于F島的核電站骡楼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏稽鞭。R本人自食惡果不足惜鸟整,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朦蕴。 院中可真熱鬧吃嘿,春花似錦、人聲如沸梦重。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琴拧。三九已至,卻和暖如春嘱支,著一層夾襖步出監(jiān)牢的瞬間蚓胸,已是汗流浹背挣饥。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沛膳,地道東北人扔枫。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像锹安,于是被迫代替她去往敵國和親短荐。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

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

  • 一般來說叹哭,最好是重用對象而不是在每次需要的時(shí)候就創(chuàng)建一個(gè)相同功能的新對象忍宋。重用方式既更加快速,也更為流行风罩。如果對象...
    Viking_Den閱讀 605評論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法糠排,類相關(guān)的語法,內(nèi)部類的語法超升,繼承相關(guān)的語法入宦,異常的語法,線程的語...
    子非魚_t_閱讀 31,664評論 18 399
  • 一般來說室琢,最好能重用對象而不是在每次需要的時(shí)候就創(chuàng)建一個(gè)相同功能的新對象乾闰。重用的方式即快速,又流行研乒。如果對象是不可...
    Ruheng閱讀 1,729評論 0 6
  • “本文參加#未完待續(xù)汹忠,就要表白#活動(dòng),本人承諾文章內(nèi)容為原創(chuàng)雹熬,且未在其他平臺發(fā)表過宽菜。” 回首在工大的點(diǎn)滴 沒有狗血...
    王國棟_a7f4閱讀 354評論 10 29
  • 孟子曰:“形色竿报,天性也铅乡;惟圣人,然后可以踐形烈菌≌笮遥” 【譯文】 孟子說:“人的身體容貌是與生俱來的;只有圣人才能夠通過...
    北冥_鯤閱讀 276評論 0 2