一般來說,最好能重用物件而不是在每次需要的時候就建立乙個相同功能的新物件。重用方式既快速,又流行。如果物件時不可變的(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
isbabyboomer每次被呼叫的時候,都會新建立乙個calendar、乙個timezone和兩個date例項,這是不必要的。下面的版本用乙個靜態的初始化器(initializer),避免了這種效率低下的情況:
class person
public boolean isbabyboomer()
}
改進後的person類只在初始化建立的時候建立calendar、timezone和date例項一次,而不是在每次呼叫isbabyboomer的時候都建立這些例項。如果isbabyboomer方法被頻繁的呼叫,這種方法將會顯著提高效能。在我的機器上,每呼叫一千萬次,原來的版本需要32 000ms,而改進後的版本只需要130ms,大約快了250倍。除了提高效能外,**的含義也更加清晰了。把boomstart和boomend從區域性變數改為final靜態域,這些日期顯然是被作為常量對待,從而使得**更易於理解。但是,這種優化帶來的效果並不總是那麼明顯,因為calendar例項的建立代價特別昂貴。 避免建立不必要的物件
下面是乙個比較微妙也比較常見的反面的例子,其中涉及可變的date物件,他們的值一旦計算出來之後就不再變化。這個類建立了乙個模型 其中有乙個人,並有乙個isbabyboomer方法,用來檢驗這個人是否為乙個babyboomer,換句話說,就是檢驗這個人是否出生於1946年至1964年之間。public...
避免不必要的物件
一般來說,最好能重用物件而不是在每次需要的時候就建立乙個相同功能的新物件。重用方式既快速,又流行。如果物件是不可變的,它就始終可以被重用。最為乙個極端的反面例子,考慮下面的語句 string s new string string don t do this 該語句每次被執行的時候都建立乙個新的st...
EJ 05 避免建立不必要的物件
極端的反面例子,每次執行都會建立乙個新的string例項 string s new string stringette don t do this 建議 string s stringette 遺留任務 boolean.valueof string 總是優先於構造器boolean string 確認...