Effective Java 筆記(二)

來源:互聯網
上載者:User
相關讀書筆記列表

NO.4 避免建立重複的對象
       如果一個對象是非可變的,那麼他中上可以被重用的,如:
  1. //不推薦,"test"本來就是一個String執行個體,如果此方法在一個迴圈中或者被頻繁的調用,將會嚴重影響效能
  2. String s = new String("test");
  3. //推薦方式
  4. String s = "test";

      對於提供靜態方法和建構函式的非可變類,推薦使用靜態方法,這樣可以避免重複建立對象,如:Boolean.vauleOf(String)方法優於建構函式Boolean(String)

      如下Person類在每次調用isBabyBoomer()方法時都需新建立對象,極大的影響了效能

  1. import java.util.*;
  2. public class Person {
  3.     private final Date birthDate;
  4.     public Person(Date birthDate) {
  5.         // Defensive copy - see Item 39
  6.         this.birthDate = new Date(birthDate.getTime());
  7.     }
  8.     // Other fields, methods omitted
  9.     // DON'T DO THIS!
  10.     public boolean isBabyBoomer() {
  11.         // Unnecessary allocation of expensive object
  12.         Calendar gmtCal =
  13.             Calendar.getInstance(TimeZone.getTimeZone("GMT"));
  14.         gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
  15.         Date boomStart = gmtCal.getTime();
  16.         gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
  17.         Date boomEnd = gmtCal.getTime();
  18.         return birthDate.compareTo(boomStart) >= 0 &&
  19.                birthDate.compareTo(boomEnd)   <  0;
  20.     }
  21. }

改進方案如下:

  1. import java.util.*;
  2. class Person {
  3.     private final Date birthDate;
  4.     public Person(Date birthDate) {
  5.         // Defensive copy - see Item 39
  6.         this.birthDate = new Date(birthDate.getTime());
  7.     }
  8.     // Other fields, methods
  9.     /**
  10.      * The starting and ending dates of the baby boom.
  11.      */
  12.     private static final Date BOOM_START;
  13.     private static final Date BOOM_END;
  14.     static {
  15.         Calendar gmtCal =
  16.             Calendar.getInstance(TimeZone.getTimeZone("GMT"));
  17.         gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
  18.         BOOM_START = gmtCal.getTime();
  19.         gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
  20.         BOOM_END = gmtCal.getTime();
  21.     }
  22.     public boolean isBabyBoomer() {
  23.         return birthDate.compareTo(BOOM_START) >= 0 &&
  24.                birthDate.compareTo(BOOM_END)   <  0;
  25.     }
  26. }

這樣類變數在類在初始化建立Calendar、Date、TimeZone時只需建立一次,已經初始化的不再進行初始化操作,效能好於前一種方法一百倍。【static變數在系統沒有調用isBabyBoomer() 方法之前,不會進行初始化(延遲初始化)】
類初始化的順序:先初始化父類的靜態代碼--->初始化子類的靜態代碼-->初始化父類的非靜態代碼--->初始化父類建構函式--->初始化子類非靜態代碼--->初始化子類建構函式。

NO.5 消除到期的對象引用
       記憶體回收行程不會對“到期引用”(永遠不會在被解除的引用)的對象進行回收。如:數組中的元素先增加再減少這種情況,下標大於size()的那一部分就是到期引用的對象。
       解決方案:

  1. public Object pop(){

  2.    if(size == 0){

  3.        throw new EmptyStackException();

  4.    }

  5. Object result = elements[--size];

  6. //自減後把原來的引用置為null
  7. elements[size] = null;

  8. return result;

  9. }

優點:1、避免記憶體流失而造成的系統崩潰(記憶體流失也常見於緩衝,由於緩衝沒有及時清除無用的條目而出現,可以使用weakHashMap來避免這種情況,參考:利用WeakHashMap避免因緩衝條目到期而造成的記憶體流失問題);
          2、程式能在第一時間拋出null 指標異常;

NO.6 避免使用終結函數       終結函數(finalizer)可以用來回收不可到達的對象,就是說對象的生命週期結束後,可以用終結函數來回收為該對象分配的資源。但是,終結函數執行線程的優先順序很低,以至於我們不敢把對時間要求比較高的對象回收讓終結函數來回收。JVM總是會延遲終結函數的執行。對於急需回收對象,可以使用tyr
finally,在finally寫回收對象的代碼,這樣就保證對象能及時被回收。       終結函數其實也是有用的。第一種情況是當作安全網,當忘了對對象顯示回收的時候,用終結函數作為最後的安全屏障。第二種情況是:普通對象通過一個本地方法
委託給本機物件叫本地對等體。本地對等體不是普通對象,所以當委託給他的對象被回收的時候本地對等體並不會被回收,所以這時候終結函數就派上用場了。最後要注意的是,當子類改寫覆蓋了超類的終結函數時候,如果不顯示調用超類的終結函數,那麼超類的終結函數將不會被執行。      總結:盡量不使用終結函數,除非作為安全網或者是用來回收不關鍵的本地資源。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.