學習目的:
- 何時以及如何創建對象
- 何時以及如何避免創建對象
- 如何確保對象適時銷毀
- 如何管理對象銷毀前必須進行的各種清理動作
1. 考慮用靜態工廠方法代替構造器
該靜態工廠方法不同于設計模式中的工廠方法,主要用于如何鮮明提供可定制化的實例構造方法。
優勢:
1. 靜態方法可以提供名稱,可以確切地描述返回的對象,更易于代碼閱讀、理解。
2. 不必每次調用的時候都創建新的對象,這樣就可以反復使用預先構建好的對象,或者將創建的對象緩存起來,有利于提升性能,這種方式在單例模式中應用較多。
3. 通過依賴于接口,而不依賴與具體實現,可以靈活返回實現該接口的子類。
4. 構造參數化實例時,代碼更加簡潔。
劣勢:
要提供可在外部實例化的類,否則優勢3無法體現,而已靜態工廠方法依然只是一個普通的靜態方法,需要提供注釋來表示她的構造功能說明。
針對劣勢方面,可以提供通用的方法名稱如valueOf,newInstance,getInstance等來標示該方法的存在意義。更主要的是在構建對象時考慮需不需要通過靜態工廠來靈活構造實例對象。
2. 遇到多個構造器參數時要考慮用Builder
在實例化某些對象時,可能需要提供多個參數,而有些參數是必須的或可選的,這個時候一般就會提供多個構造器來實例化不同的對象。
- 對象的實例化參數增多,意味著構造方法也同時增多,代碼的可讀性也隨之下降。
- 采取builder模式,完全由Builder來靈活定制對象的實例屬性,針對每個屬性提供一個set方法即可。
- 調用build方法來構建對象,并在對象構建方法中即可一次性檢測參數設置異常
3. 用私有構造器或枚舉來強化Singleton模式
- 對于實現Singleton模式一般都需要將構造器私有化,但通過Java的反射方式依然能破壞該模式,可以通過修改私有構造器在實例化第二個對象時直接拋出異常來保證單例不被破壞。
- 對象的序列化和反序列號也能破壞單例模式,需要提供readResolve方法來保證返回實例相同。
- 單元素枚舉方式來保證Singleton模式,自動提供上述兩種功能,并且能保證線程安全,是目前Singleton最佳方法。
4. 通過私有構造器來強化不可實例化的能力
有時候需要編寫一個只需要包含靜態方法或靜態域的類,用于提供一些工具性的方法,而這樣的工具類一般不希望被實例化。
在編寫類時若不提供構造方法,則系統會自動生成一個無參構造器,所以我們需要編寫一個私有構造器,并在內部直接拋出異常,你也可以在上面編寫注釋表明意圖。
5. 避免創建不必要的對象
what:
不必要的對象的鮮明特征就是對于反復使用的某一功能或方法,在每次運行時都會重新創建對象,而不是使用之前已有對象。
why:
對象的創建是需要代價的,大量創建無用對象既增加占用內存也減少了代碼運行流暢,比如創建數據庫連接對象需要較大開銷,如果能復用之前已有連接對象,對于提升性能具有顯著幫助。
how:
可以考慮在將常用對象緩存住,比如靜態域等等。但是不要總是考慮緩存對象這樣不一定能提升能力,只是對于一些創建對象開銷較大并且使用較多對象緩存,創建一些微對象對于代碼運行并沒有多少影響。
6. 消除過期的對象引用
Java是能夠自動進行垃圾回收但前提是對象沒有被引用,而在代碼編寫過程中由于緩存或一些其他使用導致在不需要該對象時,依然內部持有該對象的引用,導致該對象沒有被及時釋放,從而導致內存泄漏。所以對不再需要使用的對象盡量置為null或者對于一些對象采用弱引用。
7. 避免使用終結方法
首先終結方法是JVM自己調用的,而隨著垃圾回收算法改變,終結算法調用時刻也是不一致的,所以不要依賴終結方法做一些額外的操作,這樣會導致整個應用崩潰的,而且Java并不提供能直接命令系統進行垃圾回收的方法,System.gc()也只是建議開始系統回收的。
如果顯示覆蓋終結方法,來一定要調用父類終結方法,因為JVM不會主動調用父類的gc方法的。