【讀書筆記 - Effective Java】05. 避免建立沒必要要的對象

1. 若是對象是不可變的(immutable),它就始終能夠被重用。java

(1) 特別是String類型的對象。數據庫

String str1 = new String("str"); // 建立許多沒必要要的實例
String str2 = "str"; // "str"其自己是一個String實例,對於全部同一臺虛擬機中運行的代碼,只要它們包含相同的字符串字面常量,該對象就會被重用

(2) 同時提供了靜態工廠方法和構造器的不可變類,一般可使用靜態工廠方法而不是構造器。安全

2. 若是可變對象是已知不會被修改的,它也能夠被重用。性能

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class Person {
    private final Date birthday;
    // ...
    
    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 birthday.compareTo(boomStart) >= 0 &&
                birthday.compareTo(boomEnd) < 0;
    }
}

若是isBabyBoomer()常常被調用,那麼每一次都要建立Calendar,Date的實例,效率低下。如下方式提升了性能,代碼含義也更加的清晰。spa

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

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

 

建立多餘對象的新方法:自動裝箱(autoboxing)。但要優先使用基本類型而不是裝箱基本類型,要小心無心識的自動裝箱,否則會建立多個多餘的實例。code

 

(與第39條呼應)因重用對象而付出的代價要遠遠大於因建立重複對象而付出的代價時,提倡使用保護性拷貝對象

好比除非池中的對象是很是重量級的(數據庫鏈接池),不然不要維護本身的對象池(object pool)。通常維護本身的對象池一定會把代碼弄的很亂,同時增長內存佔用,而且還會損害性能。blog

必要時候沒實施保護性拷貝,會致使潛在的錯誤和安全漏洞內存

沒必要要的建立對象,會影響程序的風格和性能
字符串

相關文章
相關標籤/搜索