java代碼優(yōu)化——避免創(chuàng)建不必要的對象

一般來說抛虫,最好能重用對象而不是在每次需要的時候就創(chuàng)建一個相同功能的新對象松靡。重用的方式即快速,又流行建椰。如果對象是不可變的雕欺,他就始終可以被重用。

重用不可變對象

我們可以舉一個String類的例子棉姐,String類常量一旦被賦值就不可被改變屠列,就可以始終被重用。

//這是不可取的伞矩,因為每次執(zhí)行這條語句都會創(chuàng)建新的對象
String s1 = new String("hello world");

我們應(yīng)當(dāng)這樣使用下面的方式笛洛。

//java中,字符串常量存在方法區(qū)的字符串常量池中乃坤,方便相同內(nèi)容的字符串復(fù)用
String s1 = "hello world";

對于同時提供了靜態(tài)工廠方法和構(gòu)造器的不可變類苛让,通常可以使用靜態(tài)工廠方法而不是構(gòu)造器湿诊,以避免創(chuàng)建不必要的對象狱杰。例如,靜態(tài)工廠方法Boolean.valueOf(String)要比Boolean(String)要好枫吧。構(gòu)造器每次被調(diào)用的時候都會創(chuàng)建一個新的對象浦旱,而靜態(tài)工廠方法則不會。

除了重用不可變的對象外九杂,也可以重用那些不會被修改的可變對象颁湖。

重用不會被修改的可變對象

典型例子,Date對象例隆。
假如我們現(xiàn)在有一個判斷限定在8月29到8月31日可用的KFC優(yōu)惠券是否可用時
通常我們會:

 public Class Coupon{
    public boolean isExpire(){
      Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
      gmtCal.set(2016,Calendar.AUGUST,29,0,0,0);
      Date startTime = gmtCal.getTime();
      gmtCal.set(2016,Calendar.SEPTEMBER,1,0,0,0);     
      Date endTime = gmtCal.getTime();
      Date now = new Date();
      return now.compareTo(startTime) >= 0 &&
             now.compareTo(endTime) < 0; 
    }
 }

這種情況下甥捺,每次調(diào)用 isExpire 都需要創(chuàng)建一個Calendar,TimeZone和三個Date對象镀层,而其中除了now Date镰禾,其他都是的值都是不變的。這樣就白白每次多創(chuàng)建了3個對象唱逢。
建議用法

public Class Coupon{
   private static final Date START_TIME;
   private static final Date END_TIME;
   //創(chuàng)建對象時吴侦,會先執(zhí)行靜態(tài)部分。
   Static{
       Calendar gmtCal =  Calendar.getInstance(TimeZone.getTimeZone("GMT"));
     gmtCal.set(2016,Calendar.AUGUST,29,0,0,0);
     startTime = gmtCal.getTime();
     gmtCal.set(2016,Calendar.SEPTEMBER,1,0,0,0);     
     endTime = gmtCal.getTime();
   }   
   public boolean isExpire(){    
     Date now = new Date();
     return now.compareTo(startTime) >= 0 &&
            now.compareTo(endTime) < 0; 
   }
}

改進(jìn)后的Coupon類只會在初始化的時候創(chuàng)建一個Calendar坞古,TimeZone和兩個Date對象备韧,而不是每次調(diào)用isExpire 的時候。

Java中有很多這方面典型的應(yīng)用痪枫。例如织堂,Map接口的keySet方法分返回該Map對象的Set視圖叠艳,其中包含該Map中所有的鍵(key)。實(shí)際上每次調(diào)用keySet都返回同樣的Set實(shí)例易阳,當(dāng)其中一個返回對象發(fā)生變化的時候附较,其他返回對象都是對同一對象的引用,因此也會發(fā)生變化潦俺。

另外拒课,在JDK 1.5 中,有一種創(chuàng)建多余對象的新方法黑竞,即自動裝箱捕发。
它允許基本類型和對象轉(zhuǎn)換,Example: Integer int
下面有個自動裝箱錯誤的例子:

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

由于sum使用的是Long類型很魂,如此每次計算的時候扎酷,i會由long裝箱成Long,這樣一來會創(chuàng)建N個Long對象再進(jìn)行計算,速度自然慢很多遏匆。通過將sum的類型由Long轉(zhuǎn)換為long法挨,書中給出的數(shù)據(jù)是運(yùn)行時從43秒降到6.8秒。
因此幅聘,要優(yōu)先使用基本類型而不是包裝類凡纳,要當(dāng)心無意識的自動裝箱。

總結(jié)

不要錯誤的認(rèn)為"創(chuàng)建對象的代價非常昂貴帝蒿,我們盡可能的不要創(chuàng)建對象"
相反荐糜,小的對象的構(gòu)造器只做很少量的顯示工作。
所以葛超,小對象的創(chuàng)建和回收是非常廉價的暴氏,特別是現(xiàn)代JVM上更是如此(因為JVM不斷優(yōu)化)。
通過創(chuàng)建附加的對象绣张,提升程序的清晰性答渔、簡潔性和功能性,這通常是件好事侥涵。

反之沼撕,通過維護(hù)自己的對象池來避免創(chuàng)建對象并不是一種好的做法,除非池中的對象時非常重量級的
重量級對象的典型就是數(shù)據(jù)庫連接對象芜飘,從而有了數(shù)據(jù)庫連接池(因為建立數(shù)據(jù)庫連接的代價是非常昂貴的务豺,因此重用這些對象非常有意義)。
但是嗦明,一般而言冲呢,維護(hù)自己的對象池必定會把代碼弄得很亂,同時增加內(nèi)存占用,并且還會損害性能【赐兀現(xiàn)代JVM實(shí)現(xiàn)具有高度優(yōu)化的垃圾回收器,其性能很容易就會超過輕量級對象池的性能裙戏。

總之乘凸,對于不可變類以及可變的但是一旦建立后就不會改變的對象可以重用對象。在其他情況下累榜,對于重量級對象可考慮重用营勤,對其他對象要靈活創(chuàng)建,不要因為維護(hù)對象池壹罚,避免創(chuàng)建新的對象而造成額外負(fù)擔(dān)葛作,得不償失。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猖凛,一起剝皮案震驚了整個濱河市赂蠢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辨泳,老刑警劉巖虱岂,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異菠红,居然都是意外死亡第岖,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門试溯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔑滓,“玉大人,你說我怎么就攤上這事遇绞〖ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵试读,是天一觀的道長杠纵。 經(jīng)常有香客問我,道長钩骇,這世上最難降的妖魔是什么比藻? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮倘屹,結(jié)果婚禮上银亲,老公的妹妹穿的比我還像新娘。我一直安慰自己纽匙,他們只是感情好务蝠,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烛缔,像睡著了一般馏段。 火紅的嫁衣襯著肌膚如雪轩拨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天院喜,我揣著相機(jī)與錄音亡蓉,去河邊找鬼。 笑死喷舀,一個胖子當(dāng)著我的面吹牛砍濒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播硫麻,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼爸邢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拿愧?” 一聲冷哼從身側(cè)響起杠河,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赶掖,沒想到半個月后感猛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奢赂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年陪白,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膳灶。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡咱士,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出轧钓,到底是詐尸還是另有隱情序厉,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布毕箍,位于F島的核電站弛房,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏而柑。R本人自食惡果不足惜文捶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望媒咳。 院中可真熱鬧粹排,春花似錦、人聲如沸涩澡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至射富,卻和暖如春膝迎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胰耗。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工弄抬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宪郊。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像拖陆,于是被迫代替她去往敵國和親弛槐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361

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