05-避免創建不必要的對象

本節書中從避免創建不必要的對象出發,提到了大概五個方面,如下:


1、
String str1=new String("hello");每次執行都會創建String實例。
改進後
String str2="hello";
所有在同一臺虛擬機中運行的代碼,只要它們包含相同的字符串字面常量,該對象就會被重用,而不是創建新的對象。


2、
運行:

Integer integer1 = Integer.valueOf("110");
Integer integer2 = Integer.valueOf("110");
Integer integer3 = new Integer("110");

System.out.println(integer1 == integer2);
System.out.println(integer1 == integer3);

輸出:

true
false

可以發現構造器每次被調用都會創建一個新對象,而靜態工廠方法 XXX.valueOf(…) 不會。


3、
書中有這樣一個簡單模型:

public class Person {
    private final Date birthDate = null;

    public boolean isBabyBoomer() {
        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;
    }
}

代碼很簡單,isBabyBoomer()方法返回是否出生於1946~1964年期間,每當此方法被調用時,都會新建一個Calendar,一個TimeZone和兩個Date實例,這是低效率的,用一個靜態的初始化器加以改進:

public class Person {
    private final Date birthDate = null;
    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 boolean isBabyBoomer() {
        return birthDate.compareTo(BOOM_START) >= 0
                && birthDate.compareTo(BOOM_END) < 0;
    }
}

改進之後,Person類初始化時會創建Calendar、TimeZone、Date實例一次,而不用每次調用 isBabyBoomer()方法時再次創建對象。


4、使用視圖類的方法
例如,Map接口的的keySet方法返回一個已經存在的實例,keySet方法並不會返回拷貝,或者重新創建一個實例。


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而不是long!意味着程序構造了大約2的31次方多個Long實例,大約每次向Long sum中增加long時構造一個實例。將sum聲明從Long變爲long,在我電腦上運行時間從8秒減少到2秒左右。很明顯,要優先使用基本類型而不是裝箱基本類型,當心無意識的自動裝箱。

發佈了45 篇原創文章 · 獲贊 58 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章