【讀書筆記 - Effective Java】05. 避免創建不必要的對象
阿新 • • 發佈:2018-04-08
auto ive effective zone 如果 方式 一次 body 安全
1. 如果對象是不可變的(immutable),它就始終可以被重用。
(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的實例,效率低下。以下方式提高了性能,代碼含義也更加的清晰。
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)。但要優先使用基本類型而不是裝箱基本類型,要當心無意識的自動裝箱,不然會創建多個多余的實例。
(與第39條呼應)因重用對象而付出的代價要遠遠大於因創建重復對象而付出的代價時,提倡使用保護性拷貝。
比如除非池中的對象是非常重量級的(數據庫連接池),否則不要維護自己的對象池(object pool)。一般維護自己的對象池必定會把代碼弄的很亂,同時增加內存占用,並且還會損害性能。
必要時候沒實施保護性拷貝,會導致潛在的錯誤和安全漏洞。
不必要的創建對象,會影響程序的風格和性能。
【讀書筆記 - Effective Java】05. 避免創建不必要的對象