建議:避免建立不必要的物件。
一般來說,最好能重用物件而不是在每次需要的時候就建立一個相同功能的新物件。重用方式既快速,又流行。如果物件時不可變的(immutable),它就始終可以被重用。
作為一個極端的反面例子,考慮下面的語句:
String s = new String("stringette"); // DON'T DO THIS!
該語句每次被執行的時候都建立一個新的String例項,但是這些建立物件的動作全都是不必要的。傳遞給String構造器的引數("stringete")本身就是一個String例項,功能方面等同於構造器建立的所有物件。如果這種用法是在一個迴圈中,或者是在一個被頻繁呼叫的方法中,就會建立出成千上萬不必要的String例項。
改進後的版本如下所示:
String s = "stringette";
這個版本只用了一個String例項,而不是每次執行的時候都建立一個新的例項。而且,它可以保證,對於所有在同一臺虛擬機器中執行的程式碼,只要他們包含相同的字串字面常量,該物件就會被重用。
對於同時提供了靜態工廠方法和構造器的不可變類,通常可以使用靜態工廠方法而不是構造器,以避免建立不必要的物件。例如,靜態工廠方法Boolean.valueOf(String)幾乎總是優先於構造器Boolean(String)。構造器在每次被呼叫的時候都會建立一個新的物件,而靜態工廠方法則從來不要求這樣做,實際上也不會這樣做。
除了重用不可變的物件外,也可以重用哪些已知不會被修改的可變物件。
注意,在提倡使用保護性拷貝的時候,因重用物件而付出的代價要遠遠大於因建立重複物件而付出的代價。必要時如果沒能實施保護性拷貝,將會導致潛在的錯誤和安全漏洞,而不必要的建立物件則只會影響程式的風格和效能。
示例程式碼:
反例
public class Person {
private final Date birthDate;
// Other fields,methods,and constructor omitted
// DON't DO THIS!
public boolean isBabyBoomer() {
// Unnecessary allocation of expensive object
Calendar gmtCal = Calendar.getInstance(TimZone.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每次被呼叫的時候,都會新建立一個Calendar、一個TimeZone和兩個Date例項,這是不必要的。下面的版本用一個靜態的初始化器(initializer),避免了這種效率低下的情況:
class Person {
private final Date birthDate;
// Other fields,methods,and constructor comitted
/ **
* 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();
gtmCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0 && birthDate.comparte(Boom_END) < 0;
}
}
改進後的Person類只在初始化建立的時候建立Calendar、TimeZone和Date例項一次,而不是在每次呼叫isBabyBoomer的時候都建立這些例項。如果isBabyBoomer方法被頻繁的呼叫,這種方法將會顯著提高效能。在我的機器上,每呼叫一千萬次,原來的版本需要32 000ms,而改進後的版本只需要130ms,大約快了250倍。除了提高效能外,程式碼的含義也更加清晰了。把boomStart和boomEnd從區域性變數改為final靜態域,這些日期顯然是被作為常量對待,從而使得程式碼更易於理解。但是,這種優化帶來的效果並不總是那麼明顯,因為Calendar例項的建立代價特別昂貴。
相關文章
- 5、避免建立不必要的物件物件
- 第5條:避免建立不必要的物件物件
- 如何在Android中避免建立不必要的物件Android物件
- 來自Kenneth Reitz大神的建議:避免不必要的物件導向程式設計物件程式設計
- 避免不必要的排序(二)排序
- 避免不必要的排序(一)排序
- 改善C#程式建議之“避免鎖定不恰當的同步物件”C#物件
- 避免誤刪檔案的12條建議
- 第22章 物件共享,避免建立多物件——享元模式物件模式
- 建議:消除過期的物件引用。物件
- 建構函式建立物件函式物件
- 使用rebase避免公共分支出現不必要的提交記錄
- 程式設計師避免精神崩潰的9個建議程式設計師
- 工廠模式建立物件和自定義建構函式建立物件的異同模式物件函式
- 建立更好jQuery外掛的10個建議jQuery
- 私有建構函式的物件建立例項函式物件
- 5 個技巧避免不必要的瀏覽器相容性問題瀏覽器
- 建立安全PHP應用程式的實用建議PHP
- javascript基礎(this,工廠方法來建立物件,建構函式建立物件)(十六)JavaScript物件函式
- 10條建議讓你建立更好的jQuery外掛jQuery
- IT人士建立職業安全感的5個建議
- 建立自己的遊戲工作室的72個建議遊戲
- 多執行緒的建立 兩種方式以及使用建議執行緒
- 建立派生類物件,建構函式的執行順序物件函式
- Tom Rassweiler:分享快速建立有效遊戲原型的相關建議遊戲原型
- 07物件的建立物件
- js Date()建構函式建立時間日期物件JS函式物件
- JavaScript物件與建立物件的方式JavaScript物件
- 大家都來注意下了:程式設計師避免精神崩潰的9個建議程式設計師
- sql tuning advisor(STA) 建議 建立sql profileSQL
- new BigDecimal時,請使用字串作為引數為最佳,避免不必要的麻煩Decimal字串
- 韓國建立基於區塊鏈的“建議評估系統”區塊鏈
- 使用32位 Windows 作業系統時避免記憶體問題的五個建議Windows作業系統記憶體
- 物件的建立和分配物件
- JavaScript 建立物件的方式JavaScript物件
- js建立物件的方法JS物件
- Java 物件建立的流程Java物件
- js建立物件的方式JS物件