學習effective java-5創建和銷燬對象之避免創建不必要的對象

該知識點是自己從書籍中學習的筆記。

  1.重複使用同一對象比每次創建與該對象功能一樣的新對象好。重複使用對象效率更快、更優雅。如果一個對象是一直不變的話,最好是重複使用。

  比如下面的使用就不太好:

   String s = new String(“Hello”);//不太好,每次都會創建新的String對象,而該對象是不需要的。

  可以替換成:String s = “Hello”;//在同一個jvm中,“Hello”會保存在String池中,在堆中不會生成新的對象。

  2.爲了避免創建不必要的對象,你可以使用靜態工廠方法和構造方法(前者性能較後者好,因爲後者始終會創建一個新對象)。但是在實際運作中,並不用靜態工廠方法。

  3.除了重複利用一層不變的對象,創建好的並且對象的設置不會被修改的可變對象也是可以重用的。例子1:

class TEST {

    private final Date birthDate;

 

    public Person(Date birthDate) {

       this.birthDate = birthDate;

    }

 

    // Other fields, methods, and constructor omitted

    // DON'T DO THIS!

    public boolean isBabyBoomer() {

       // Unnecessary allocation of expensive object

       Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

       gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);

       Date boomStart = gmtCal.getTime();

       gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);

       Date boomEnd = gmtCal.getTime();

       return birthDate.compareTo(boomStart) >= 0

              && birthDate.compareTo(boomEnd) < 0;

    }

}

例子2:

class TEST1 {

    private final Date birthDate;

    // Other fields, methods, and constructor omitted

    /**

     * The starting and ending dates of the baby boom.

     */

    private static final Date BOOM_START;

    private static final Date BOOM_END;

    static {

       Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

       gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);

       BOOM_START = gmtCal.getTime();

       gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);

       BOOM_END = gmtCal.getTime();

    }

 

    public Person1(Date birthDate) {

       this.birthDate = birthDate;

    }

 

    public boolean isBabyBoomer() {

       return birthDate.compareTo(BOOM_START) >= 0

              && birthDate.compareTo(BOOM_END) < 0;

    }

}

明顯例子2比例子1好,因爲比較的時間不會每次都生成。

4.從jdk1.5開始,要優先考慮原生態的數據類型。下面的例子說明自動裝箱後的速度比原生態慢:

    public static void main(String[] args) {

       Long sum = 0L;

       for (long i = 0; i < Integer.MAX_VALUE; i++) {

       sum += i;

       }

       System.out.println(sum);

  }

因爲sum是Long對象的,要裝箱2的31次。如果將Long修改成long,就快了。

5.如果類的構造方法本身就小,就不太推薦使用對象池的方法來管理已存在的對象。因爲編寫對象池會增加代碼難度,比直接建立新對象的花銷更大。

使用對象池較好的一個例子就是數據庫的鏈接池,因爲鏈接數據庫本身的花銷就大,所以建立一個鏈接池存放已經有的對象就比較好。但是對於較小的類的構造方法的話,還是使用直接創建對象較好。

6.當然並不是重用已有的對象就是比較完美的,當在保護性拷貝(defensive copying)的場合時,就比重複使用對象較好。在保護性拷貝的情況下沒有使用保護性拷貝的話,會導致潛在的錯誤和安全漏洞;而使用重複的對象僅僅是在性能和風格上有問題而已,其風險不高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章