標籤:java 開發經驗 編碼
關於Effective java 這本書,自己的一些總結性的思考。篇幅可能不按照目錄來,因為自己喜歡先看哪一章就直接閱讀了。不過能確定的是,每一章都會有總結。歡迎大家拍磚與補充。
1. 考慮用靜態工廠的方法代替構造器。優點:有名字,不必每次建立對象,返回任何子類型對象,簡潔的代碼。缺點:該類將不能被子類化(複合大於繼承,也是優點),不方便doc工具輸出文檔,一般約定的命名規則:
valueOf 轉換類型
getInstance 獲得對象執行個體
newInstance 建立新的對象執行個體
getType 獲得返回對象的類型
newType 置入返回對象的類型,在不同類中方便區別Factory 方法
2. 遇到多個構造器參數(4個以上)時要考慮用構建器。重疊構造器代碼冗長,後期不能有效維護,javaBean模式的構造器在多線程下不安全,沒有達到類不可變性,原因是暴露出去了setter方法。Builder模式的構造器是不錯的選擇。
Class A{
//屬性
static class Bulid{
//屬性
Bulid(){//接受初始化參數 }
Bulid a(){ Return bulid; //添加參數返回Bulid產生調用鏈}
..
A bulid(){ return A(this);} //構造器對象初始化A對象返回
}
A(Bulid b){ //將b中參數傳遞給A參數域}
}
3. 用私人構造器或者枚舉類型強化Singleton屬性。對於私人構造器有2種方案,匯出公有的靜態成員的執行個體與提供靜態工廠返回私人的靜態成員執行個體。但是並非安全的,採用AccessibleObject,通過反射技術可以調用私人的構造器,產生第二對象,解決方案是產生第二執行個體的時候拋出異常。使得Singleton序列化,(implementsSerializble)+(執行個體域transient)+(readResolve方法返回執行個體)。單元素的枚舉類型是實現Singleton的最佳方案。
4. 通過私人構造器強化不可執行個體的能力。提供顯示的構造方法比編譯器提供預設的好,特別是私人的構造器,並在私人的構造器中拋出AssertionError。由於這一技術的使用,使得該類無法被子類化。
5. 避免建立不必要的對象。考慮的方向有,字串類,static{}域,視圖view(Map中的set等),自動裝箱拆箱,對象池object pool。
6. 消除到期的對象引用。Stack.pop後,不使用的元素未置空引起的記憶體泄露,磁碟交換,嚴重的情況導致OOM異常。記憶體泄露另一個來源是緩衝問題。如果key中不在保持引用,那麼WeakHashMap自動清除到期的key。如果隨著時間的增長,某些key可能不用了,那麼採用LinkedHashMap。removeEldestEntry方法將實現這一方案。第三個來源是監聽器和其他回調,採用保持弱引用的方法,即WeakHashMap的方案來處理。關於記憶體泄露的一個Heap剖析工具Heap Profiler。
7. 避免使用終結方法。Finalizer的方法JVM並不一定執行,即使調用了System.gc。System.runFinalization。除非使用System.runFinalizersOnExit,Runtime.runFinalizersOnExit方法(ThreadStop,不建議使用)。嘗試著使用try{}finally{}結構來顯示的調用終結方法確保及時終止。如果子類覆蓋了超類的終結方法,但是忘記手工調用超類的終結方法super.finalize,那麼超類的終結方法將永遠也不會被調用。
如果將本章內容聯絡到實際的編碼之中呢?我也進行的思考,由於自己在類庫方面開發經驗很少,沒有通讀過jdk全部的源碼,所以有些建議不一定準確。
1.當你在建立類的時候,就應當想這個類未來要做什嗎?是什麼類型?構造參數多嗎?適用經驗1,2,3,4
2.當你在編寫某段代碼的時候,你應當想到該對象是否可以重複利用?如果是集合類,那麼思考,傳入的對象是否未來會不使用?如果覺得這段代碼或者方法,以及涉及到該類在全域上隨著運行會消耗較大的記憶體?那麼可以嘗試著使用5,6,7三個總結來處理這種問題。
畢竟上面都是一些方法論,在實踐過程中,需要自己有經驗的去判斷如何做才是最優的(可能是目前最優,亦或者未來效果很好),這些都是不同情境下產生的,並不一定會有效去解決。
Effective java經驗之談,建立和銷毀對象