規則1、用靜態方法代替類構造函數。
以前也用過,不過主要是在寫單例模式的時候用過,看完以爲使用的場景還比較多,好比一、類的實例化方法能夠有具體的名字,方便使用;二、也能夠返回類的子類對象。缺點以前還未想過,看完貌似有一點比較注意,類若是沒有共有的或者受保護的構造函數,則該類將沒法被繼承。
規則2、使用私有構造函數強化singleton屬性
以前一直是這樣用的,具體的singleton模式,講的不少,不在此處詳解了。可是裏面有講到所謂的序列化和反序列化的東西,貌似通常的singleton模式裏面不多說起,由於不多有序列化的singleton模式例子,在此點一下。
規則3、經過私有化構造函數強化不可實例化的能力
常見的應用場景,如工具類,貌似以前不多對構造函數下手,仔細想一想,仍是須要進行私有化構造函數。
規則4、避免建立重複的對象
若是一個函數被頻繁的調用,則能夠考慮將此函數中的變量放到函數以外,這樣能夠減小建立對象帶來的性能損失。固然,也不要以爲建立對象代價很昂貴,就如今的JVM來看,通常不須要特地去維護對象池,除非是有必要,好比數據庫鏈接池,仍是頗有必要的,具體還有哪些,還須要繼續摸索,能夠進行性能上的測試和比對。
規則5、消除過時的對象引用
GC主要是回收沒有被引用的對象,若是存在對象被引用,則GC是不會去回收的,除非顯示的通知GC,通常來講若是類本身管理它的內存,則須要警戒內存泄漏的問題。
規則6、避免使用終結函數
日常本身寫的代碼中,基本從未用到終結函數,不過看了這個規則以後,發現,有些地方仍是須要的,好比做爲安全網(還未明白啥意思),或者終止非關鍵的本地資源。一旦使用,則將考慮使用終結函數守衛者,保證終結函數被正確的執行。若是能夠的化,儘可能顯示調用終止函數。
java
public class Foo { private final Object finalizerGuardian = new Object(){ @Override protected void finalize() throws Throwable { //finalize outer Foo Object super.finalize(); } }; }
規則7、在改寫equals的時候請遵照通用約定
第一次接觸這個是使用了Hibernate,並且使用了Set.contains()函數所必需要提供的。當時的邏輯就是經過判斷ID是否相等。
通用約定,對於學過數學的人來講仍是比較簡單:
一、自反性:x.equals(x)=true
二、對稱性:x.equals(y)=true => y.equals(x)=true
三、傳遞性:x.equals(y)=true && y.equals(z)=true => x.equals(z)=true
四、一致性:x.equals(y) is always true or false
五、非空性:x.equals(null) = false,equals方法中最好先進行instanceof檢查
規則8、改下equals方法的時老是要改寫hashCode方法
沒什麼好說的,若是用到了hashMap等之類的,必需要重寫,比較好的重寫方法就是作移位操做?
規則9、老是要改寫toString方法
toString的通用約定指出,被返回的字符串應該是一個簡潔的,但信息豐富,且易於閱讀的表達形式。好比能夠將toString變成json格式的輸出。
規則10、謹慎的修改clone
貌似還從未接觸過這個函數。貌似提供一個比本身複製對象及其內容更快的實現。
規則11、考慮實現Comparable接口
若是實現此接口,那麼使用Array.sort將很是簡單
規則12、使類和成員的可訪問能力最小化
使得程序間耦合度下降,模塊化程序,使得能夠並行開發,提升開發效率,這個屬於設計原則的問題。
規則十3、支持非可變性
即實例不能夠修改。如String、BigInteger等,和一般的POJO類來比較 就是提供所有成員變量的一個構造函數,而後私有化全部的成員變量和成員函數。程序員
規則十4、複合優先於繼承
當子類繼承超類時,超類的API會顯示給子類,若是超類API發生變化,子類又剛好使用了超類的API,若是超類的API發生變化,則子類也將進行修改,形成子類很是脆弱。比較好的作法是,進行復合,也就是所謂的裝飾模式,這樣就能夠隱藏超類API的缺陷,擁抱變化。只有子類真的是超類的「子類型」的時候,繼承纔是合適的。
規則十5、要麼專爲繼承而設計,並給出文檔說明,要麼禁止繼承
該類的文檔必須精確的描述改寫每個方法所帶來的影響。好的API文檔應該描述一個方法作了什麼工做,而並不是描述它是如何作到的。一個例子:超類的構造函數調用了超類中的一個API,若是子類重寫了這個API,將致使程序失敗。禁止子類化的方案,一、類聲明爲final,二、把全部的構造函數變成私有或者包級私有。
規則十6、接口優先於抽象類
由於java中只容許單繼承,能夠實現多個接口,因此接口使得安全地加強一個類的功能稱爲可能。通常來講,能夠將接口和抽象類進行組合,對於每一個指望導出的重要接口,都提供一個抽象的骨架實現。
規則十7、接口只是被用於定義類型
不用定義常量接口,比較好的方法就是定義常量工具類,私有化構造函數。
規則十8、優先考慮靜態成員類
嵌套類是指被定義在另外一個類的內部類,若是這個嵌套類未來可能用於其餘的某個環境,那麼就應該是頂層類。嵌套類有四種:靜態成員類、非靜態成員類、匿名類和局部類。除了第一種,其餘都被稱爲內部類。靜態成員類就是加了static關鍵字,若是聲明的成員類不要求訪問外圍實例,那麼請使用靜態成員類。匿名類用過不少了,不少回調函數裏面就應用了匿名類做爲最後一個參數,須要注意的一點就是,若是匿名類篇幅很長,設計的時候就考慮獨立出來,常見用法如過程對象(Thread等)、靜態工廠方法內部、複雜的類型安全枚舉類型、一般只實現接口或者超類中的方法。局部類是最少使用的類,在任何能夠聲明局部變量的地方,均可以聲明局部類。總結:若是嵌套類在單個方法以外仍然可見,或者太長,不適合放在一個方法內部,那麼就應該使用成員類;若是成員類的每一個實例都須要一個指向其外圍實例的引用,則把成員類作成非靜態的,不然就作成靜態的。假設一個成員類屬於一個方法的內部,若是你只須要在一個地方建立它的實例,而且已經有了一個預先存在的類型能夠說明這個類型能夠說明這個類的特徵,則把它作成匿名類;不然就作成局部類。
規則十9、用類代替結構
規則二10、用類層次來代替聯合
類層次提供了類型安全、代碼簡潔明瞭、容易擴展、反映出類型的本質。
規則二11、用類代替enum結構
定義一個類來表明枚舉類型的單個元素,而且不提供任何公有的構造函數。相反,提供共有的靜態final域,使枚舉類型中的每個常量都對應一個域。
規則二12、用類和接口代替函數指針
函數指針更像是策略模式的實現。
規則二十3、檢查參數的有效性
沒什麼好說的,只是不要過分檢查有效性。
規則二十4、須要時使用保護性拷貝
爲了保護對象實例的內部信息避免受到攻擊,對於構造函數的每一個可變參數進行保護性拷貝是必要的。注意:保護性拷貝動做是在檢查參數的有效性以前進行的,而且有效性檢查是針對拷貝以後的對象,而不是原始的對象。若是類提供了內部域的訪問,那麼要使得它返回可變內部域的保護性拷貝。
規則二十5、謹慎設計方法的原型
謹慎選擇方法的名字;不要過於追求提供便利的方法;避免長長的參數列表(考慮將一個方法分解成多個方法;建立輔助類);對於參數類型,優先使用接口而不是類;謹慎的使用函數對象(常見的就是使用匿名類)。
規則二十6、謹慎的使用重載
重載的方法選擇是在編譯時的參數類型進行,即編譯的時候參數類型決定調用的重載方法,而改寫的方法選擇是在執行時的參數類型,因此謹慎使用重載。一個安全而保守的策略是,永遠不要導出兩個具備相同參數數目的重載方法。
規則二十7、返回零長度的數組而不是null
規則二十8、爲全部導出的API元素編寫文檔註釋
註釋該寫清楚作了什麼,而不是寫如何作。同時應該列舉全部的前提條件和後置條件,描述其反作用(如開啓了一個後臺線程)、和該類的線程安全性。
規則二十9、將局部變量的做用域最小化
儘可能在其第一次使用它的地方聲明,否則等到使用該變量的時候,可能已經不記得前面該變量聲明時的類型和初始值了,也不肯定其當前值。同時能夠變量剪切複製帶來的粗心的錯誤。
規則三10、瞭解和使用庫
每一個程序員應該熟悉java.lang java.util java.io中的內容,其餘庫能夠根據須要的時候再學習。
規則三11、若是要求精確的答案,避免使用float和double。
貨幣計算請使用BigDecimal、int或者long類型。
規則三12、若是其餘類型更適合,請避免使用字符串。
我的也很排斥這種作法,由於若是使用字符串,則只能使用字符串提供的一些方法和工具,有時候會顯的很笨拙,可是偶爾也會使用字符串,在一些特殊的地方。
規則三十3、瞭解字符串鏈接的性能
爲鏈接n個字符串而重複的使用字符串鏈接操做符,要求n的平方級的時間,由於字符串是非可變的,當兩個字符串被鏈接的時候,他們的內容都要拷貝!爲了得到可接受的性能,使用StringBuilder代替String。
規則三十4、經過接口引用對象
能夠保持程序的靈活性,有時候,只須要修改一行代碼,就能夠改變整個程序。若是須要額外的實例的方法,則須要經過類應用對象。
規則三十5、接口優先於反射
性能、可讀性等方面會有損失,可是對於一些特殊的用途來講,使用反射仍是必須的。
規則三十6、謹慎的使用本地方法
本地方法的用途:一、提供訪問與平臺相關的設施的能力,二、提供訪問老式代碼庫的能力,三、經過本地語言實現性能關鍵的部分。可是隨着1.3發行版本的推出,使用本地方法來提升性能的作法已經不提倡了。並且使用本地方法不安全。
規則三十7、謹慎的進行優化
努力寫好的程序而不是快的程序。應該在設計的時候考慮好的結構,性能的優化能夠在完成程序以後,固然也不是說編寫程序的時候忽略性能問題。
規則三十8、遵照廣泛接受的命名習慣
不嚴格的講,命名慣例分爲兩大類:字面的和語法的。
規則三十9、只針對不正常的條件才使用異常
不要依賴異常去幫你提升性能等。
規則四10、對於可恢復的條件使用被檢查的異常,對於程序錯誤使用運行時異常
沒什麼好說的,編寫的時候爲了可用性,須要對異常進行合理的使用。
規則四11、避免沒必要要的使用被檢查的異常
規則四12、儘可能使用標準的異常
瞭解java提供的常見異常以及相關的含義。
規則四十3、拋出的異常要適合於相應的抽象
若是一個方法拋出的異常與它執行的任務沒有明顯的關聯關係,這種情形會令人不知所措。高層的實現應該捕獲低層的異常,同時拋出一個能夠按照高層抽象進行解釋的異常。
規則四十4、每一個方法拋出的異常都要有文檔
沒什麼好說的。
規則四十5、在細節消息中包含失敗=捕獲消息
爲了捕獲失敗,一個異常的字符串表示應該包含全部「對異常有貢獻」的參數和域的值。
規則四十6、努力使失敗保持原子性
就是說一個失敗的方法調用應該使對象保持「它被調用以前的狀態」,具備這種屬性的方法被稱爲具備失敗原子性。這樣就能夠從異常中恢復過來。一般的途徑是:一、設計一個非可變對象;二、在執行操做前檢查參數的有效性;三、對計算過程調整順序,使得任何可能會失敗的計算部分都發生在對象狀態被修改以前;四、編寫一段恢復代碼;五、在對象的一份臨時拷貝上執行操做,當操做完成後再把臨時拷貝中的結果複製個原來的對象。錯誤(相對異常)一般是不可恢復的。
規則四十7、不要忽略異常
空的catch塊會是異常達不到應有的目的,至少也應該包含一條說明,用來解釋爲何忽略掉這個異常是合適的。
規則四十8、對共享可變數據的同步訪問
synchronized關鍵字。volatile修飾符能夠保證任何一個線程在讀取一個域的時候都將會看到最近剛剛被寫入的值。
規則四十9、避免過多的同步
過多的同步可能會致使性能下降、死鎖,甚至不肯定的行爲。須要對客戶代碼進行限制,若是客戶代碼也開啓了線程,那麼可能會出現死鎖的現象。一般,在同步區域內應該作儘量少的工做。
規則五10、永遠不要在循環的外面調用wait
老是使用wait循環模式來調用wait方法。循環通常用於在等待的先後測試條件。
規則五11、不要依賴於線程調度器
線程調度器會依賴具體的JVM實現,因此不要依賴於線程調度器。
規則五12、線程安全性的文檔化
一個類爲了可被多個線程安全使用,必須在文檔中清楚的說明它所支持的現場安全性級別。
規則五十3、避免使用線程組
除了線程、鎖和監視器之外,線程系統還提供了一個基本的抽象,即線程組,可是它並未提供所說起的任何安全功能!
規則五十4、謹慎的實現Serializable
一旦一個類被髮布,則"改變這個類的實現"的靈活性將大大下降。並且增長了錯誤(bug)和安全漏洞的可能性,範序列化是機制是一種語言以外的對象建立機制。隨着一個類的新版本的發行,相關的測試負擔增長了。
規則五十5、考慮使用自定義的序列化形式
若沒有認真考慮默認序列化形式是否合適,則不要接受這種形式。除非自行設計的自定義序列化形式與默認的基本相同。transient修飾符代表這個實例域將從一個類的默認序列化形式中省略掉。
規則五十6、保護性的編寫readObject方法
在調用defaultxx函數以後,須要進行域進行校驗。
規則五十7、必要時提供一個readResolve方法
若是一個單例模式實現了序列化接口,那麼它就再也不是單例。除非編寫正確的readResolve方法。對於一個正在範序列化的對象,若是它的類定義了readResolve方法,而且是正確的,那麼反序列化以後,新建立對象上的readResolve方法就會被調用。同時readResolve方法能夠做爲保護性的readObject方法的一種保守的替代選擇。數據庫
至此,該本書已經閱讀完畢,可是不少東西依然有待實踐去領悟,所謂溫故而知新也。關於序列化的地方,貌似還歷來未考慮過,確實應該去體會體會。
json