第一條:考慮用靜態工廠方法代替構造器。
第二條:遇到多個構造器參數時要考慮用構造器。
第三條:用私有構造器或者枚舉類型強化Singleton屬性。
第四條:通過私有構造器強化不可實例化的能力。
第五條:避免創建不必要的對象。
String s=new String("abcd"); //Don't do this.
改進后的版本:
String s="abcd"; //只有一個String實例。
構造器在每次被調用是都會創建一個新的對象,而靜態工廠方法則從不要求這樣做。
除了重用不可變的對象之外,也可以重用那些已知不會被修改的可變對象。
第六條:消除過期對象的引用。
如果一個棧先是增加,然后收縮,那么從棧中彈出來的對象將不會被當做垃圾回收,即使使用棧的程序不再引用執行對象。這是因為棧內部維護著對這些對象的過期引用。所謂過期引用就是永遠不會被解除的引用。這類問題的修復方法很簡單:一旦對象引用已經過期,只需清空這些引用即可。
內存泄露的另一個常見來源是緩存。
內存泄露的第三個常見來源是監聽器和其回調。如果實現了一個API,客戶端咋這個API中注冊回調,卻沒有顯示地取消注冊,除非采取某些動作,否則它們就會積聚。確保回調被立即當做垃圾回收的最佳方法是只保留它們的弱引用,例如,只將它們保存在WeakHashMap中的鍵。
第七條:避免使用終結方法。
注重時間的任務不應該由終結方法來完成。例如,用終結方法來關閉已經打開的文件,這是嚴重錯誤的,因為打開文件的描述符是一種很有限的資源。由于JVM會延遲執行終結方法,所以大量的文件會保留在打開狀態,當一個程序再不能打開文件時,它可能運行失敗。
不應依賴終結方法來更新重要的持久狀態。例如,依賴終結方法來釋放共享資源(比如數據庫)上的永久鎖,很容易讓整個分布式系統垮掉。
使用終結方法有一個非常嚴重的性能損失。
如果類的對象中封裝的資源(例如文件或者線程)確實需要終止,只需提供一個顯示的終結方法,并要求該類的客戶端在每個實例不再有用的時候調用這個方法。該實例必須記錄下自己是否已經被終止:顯示的終止方法必須在一個私有域中記錄下“該對象已經不再有效”。如果這些方法是在對象已經終止之后被調用,其他方法就必須檢查這個域,并拋出IllegalStateException異常。顯示終結方法通常與try-finally結構結合起使用。