《Effective Java》總結

導語

《Effective Java》是和《Thinking in java》齊名的java進階書籍。做者參與了JDK標準庫的編寫工做,對於此書的學習,讓我收穫不少。好記性不如爛筆頭,我決定好好總結一下。本書主要內容有11章,分別從各個方面闡述了做者對於java代碼編寫的體會。我看的是第二版,目前最新版已是第三版了,可是尚未在國內翻譯出版。這就是英語很差的侷限之處~java

建立和銷燬對象

  1. 做者認爲,使用構造方法構造對象是不優雅的。咱們應該是用工廠方法來構建對象。一來能夠用語義化的靜態方法名來避免構造方法重載形成的迷惑性,二來能夠在構造對象時進行如懶加載,校驗等相關控制,由於構造方法調用後必定會返回一個新的分配了堆內存的對象引用。一般的方法名爲:valueOf,of,getInstance,newInstance,getType,newType等。
  2. 做者認爲,對象參數過多時,爲了不冗長的setter方法調用,應該使用Builder設計模式。同時builder對象能夠做爲參數傳遞給相關方法。此處能夠配合Lombok
  3. 做者認爲構造單例的最好方式是枚舉,同時應該注意對象序列化對單例形成的破壞。
  4. 做者認爲只包含靜態方法和靜態域的類應該私有構造器,於是不可實例化,不能被繼承(子類實例化時會調用父類構造器)。我的認爲也可使用abstarct關鍵字。
  5. 做者認爲避免建立沒必要要的對象,如String s =new String("hello"),這裏其實就重複定義了字符串,形成了內存浪費和GC壓力。還有就是循環語句中的某些對象能夠在語句外面建立,在整個循環中重用。避免自動裝箱形成的頻繁建立對象。1522157122995.png編程

  6. 在咱們本身管理內存時,要注意消除過時對象的引用,讓JVM及時回收內存。咱們本身管理內存的典型場景爲咱們在全局範圍內持有一個數組,咱們本身管理本身的數組內存,進行數據的增刪改。咱們要及時的將不用的對象引用從數組中經過置爲null去掉。讓GC內存回收內存。52215766484
  7. 避免使用finalize方法。在此方法歷寫業務的最大問題時,該方法的調用時間是不必定的。由於GC線程的優先級很低,因此該方法的調用時機是不可控的,且性能開銷很大。只建議在某些特定狀況下做爲安全網方法,即最後一道捕捉漏網之魚的方法。
  8. 應該重寫equals方法。此處能夠配合Lombok
  9. 應該同時重寫hasCode方法。此處能夠配合Lombok
  10. 應該要覆蓋toString方法。便於調試。此處能夠配合Lombok
  11. 應該謹慎的使用clone方法。由於存在淺克隆問題。
  12. 對於值對象類,應該合理的實現Comparable方法。此處能夠配合guava的Ordering。
  13. 應該使類的成員可見性在可能的狀況下最小。由於一旦類的成員暴露,那就成爲建立者和調用者之間的約定。那麼類的建立者就要對這些暴露的成員的穩定性負責,不能隨意修改約定。
  14. 應該經過方法訪問域而不是直接訪問域。由於能夠在方法中進行相關控制。
  15. 應該使對象的可變性最小。即,除非必要,全部的域都應該用final修飾,全部域都應該是私有的,全部類都不能被拓展。被拓展的類可能會被破壞封裝性,即,拓展的過程當中,須要去了解被拓展的類的內部實現,而不只僅是被拓展的類暴露出來的API。
  16. 複合優於繼承。如上所述,繼承破壞了封裝性,同時複合更穩定,不會受到被複合的類的結構的改變的影響。經過複合和轉發(適配器模式)能夠方便的實現繼承的效果。同時能夠經過asType方法暴露一個被複合的類的視圖模擬多態。
  17. 繼承是一種約定。要麼提供豐富和負責任的文檔告知方法的自用性,並測試被繼承後的風險,要麼就經過final禁止被繼承。
  18. 接口優於抽象類。由於單繼承的侷限性,同時接口之間並不必定和類同樣是分層關係。經過mixin接口(如Comparable接口),能夠構建功能豐富的類,而且能夠靈活的實現多態。爲了便捷的實現接口,能夠提供一個接口默認實現骨架類(Wapper)。
  19. 接口只用於定義類型,便於實現多態。不該該用來定義常量,常量屬於不一樣的實現類的內部實現,不該該放在接口中做爲API約定。
  20. 經過在類中添加一個type字段來區分不一樣類型是不夠OOP的,應該經過類的繼承來實現層次。將相同的部分抽象成父類,type字段的每個值都做爲一個拓展子類。添加本身的字段和方法。52215939417
  21. 用函數對象表示策略,java8以前不支持函數式編程的迂迴。
  22. 優先考慮靜態內部類。靜態內部類時訪問權限的最小域。若是一個類只在本類中使用,就能夠定義爲私有的靜態內部類。固然,它實現的接口能夠有公開的訪問權限。
  23. 不要使用原生類型(raw type)。對於泛型類,都應該使用參數化類型。
  24. 使用SupressWarn()壓制編譯器警告。前提是必需要了解警告的內容,同時將壓制的區域最小化,避免出現詭異的問題。
  25. 列表優於數組。兩個緣由,數組是協變的,容易產生類型轉換異常。數組不支持泛型。
  26. 使用泛型。避免類型轉換異常。
  27. 使用泛型方法。便捷的類型推導可使代碼更簡潔。
  28. 使用有限制的類型通配符來提升API的靈活性。
  29. Class類是參數化類型,有不少類型相關的方法。如:cast等。注意靈活使用。
  30. 常量推薦使用枚舉定義。
  31. 不要在業務中使用枚舉的ordinal屬性,應該自定義一個實例域。
  32. 使用EnumSet來代替位域。
  33. 使用EnumMap代替序數索引。枚舉做爲map的key時。
  34. 枚舉能夠實現接口(由於枚舉是一種特殊的類)。
  35. 註解優於命名模式。經過命名約定來指定範圍,不如在類或類成員上添加註解標記。
  36. 使用Override註解來進行編譯器檢查。
  37. 某些只在類上的標記,能夠考慮標記接口。如CloneableSerialble
  38. 檢查參數,快速失敗。
  39. 必要時對參數進行拷貝。若是方法調用者將引用傳遞給方法後,在方法外對引用指向的對象進行了修改,可能會形成詭異的不可預期的錯誤。52216079682
  40. 謹慎設計方法簽名。這部份內容太多,也很經典。建議時不時翻下這一節。方法名要合乎約定;不要過度追求方法便捷,除非某個功能太經常使用能夠提供一個便捷方法,否則的話提供一個功能齊全的方法就好;避免過長的參數列表,若有必要,能夠提供一個輔助類;注意方法正交性,即功能不要重複。參數優先使用接口,離散參數如布爾參數優先使用枚舉。
  41. 慎用重載。能夠定義一個參數相關的方法名。
  42. 慎用可變參數。不安全,代碼不美觀。建議是一個必要參數加一個可變參數。
  43. 返回空數組或空集合,而不是null。
  44. 爲全部公開API編寫文檔。
  45. 局部變量做用於最小化。
  46. 儘量的使用類庫。
  47. 精確計算使用大數類型。
  48. 基本類型優於包裝類型。
  49. 儘可能避免使用字符串。
  50. 當心字符串鏈接的性能。
  51. 接口優於反射機制。反射效率低,沒法進行編譯期檢查。
  52. 謹慎的進行優化。前期能跑就行,不要進行沒有目的的優化。
  53. 不要用異常進行分支控制。
  54. 豐富異常信息。
  55. 不要忽略異常。
  56. 優先使用標準的異常。
  57. 併發編程中,儘可能使用併發工具類
  58. 序列化沒啥用啊,不說了。設計模式

總結

我感受這本書就是很厲害,尤爲是帶我理解了Super Type Token這個關於反射和泛型的概念。固然了,那又是一篇博客了,找時間我會娓娓道來的。這本書裏關於類和方法的內容很精闢,讓我理解了一些關於OOP迷惑。其實值得我多刷好幾遍,可是我就匆忙的兩三天刷完了。。。心態浮躁。第四章第五章找個午休再翻翻吧。數組

第一次正式的開始用Markdown寫博客,感受本身很極客。就是博客園的Markdown主題有點太low了。之後我就用這個來寫博客啦。。。安全

後面的博客計劃是總結下字節碼,反射和泛型。還想着刷一本Zookeeper的書寫一寫Zookeeper的相關實踐。就是心情太浮躁,作事效率過低,拖拖拉拉讓我很煩惱。併發

加油吧。app

相關文章
相關標籤/搜索