posts - 11, comments - 10, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          Effective Java讀書筆記

          Posted on 2006-06-29 11:32 繁星滿空 閱讀(1037) 評論(0)  編輯  收藏 所屬分類: Java

          作者簡介:Joshua BlochGoogle的首席工程師,之前是Sun的杰出工程師,他領導了大量的java平臺設計和實現工作,包括jdk5.0的語言增強和集合框架,擁有卡內基.梅隆大學的計算機科學的博士學位。

          ?

          本書的目標是幫助你最有效的運用java編程語言及其基本庫,java.langjava.utiljava.io。本書由57個條目組成,每個條目傳達一個原則,這些原則是最有經驗的程序員在實踐過程中的一些有用的做法。

          Creating and Destroying Object

          ?

          Item 1: 考慮用靜態工廠方法替代構造器

          public static Boolean valueOf(boolean b) {

          ??? return (b?Boolean.TRUE:Boolean.FALSE);

          }

          考慮在構造函數之外提供staticfactory mothod。

          優點:1.名字可不與類名相同,可以采用更易理解的名稱。2.不必每次都返回一個新的對象。3.可以返回子類型。

          缺點:1.無法被繼承。2.和其它static方法無法區分。

          ?

          Item 2: 通過添加私有構造器來加強單例屬性(singletom property)

          public class Hello {

          public static final Hello Instance = new Hell();

          ??? private Hello() {}???????????????????????????????????????

          }

          public class Hello {

          private static final Hello Instance = new Hell();

          ??? private Hello(){}

          ??? public static Hello getInstance() {

          ??? ????return Instance;

          ??? }

          }

          第二種方法可以方便改變。

          如果想讓singleton類成為serializable,除了implements Serializable外,還要提供readResolve()方法返回該單例。

          ?

          Item 3: 為構造器添加private以避免被實例化

          對于只是由static屬性和方法構成的工具類,要為構造器添加private,以免被實例化,而不添加的話,則可能有默認的構造器。

          ?

          ?

          Item 4: 避免創建重復的對象

          尤其是創建比較昂貴的。

          對不可修改的對象盡量進行復用,這樣效率和性能都會提高。例如如果循環100String s = new String("hello")將創建100個對象 循環100String s = "hello";則只創建了一個對象。很好的進行了復用。

          ?

          Item 5: 消除絕對的對象引用

          內存泄漏,在cache里易發生。

          public Object pop(){

          if(size == 0) {}??

          ? ??return elements[size--];

          }

          public Object pop() {

          if(size == 0) {}

          ? ??Object obj = elements[--size];

          ? ??elements[size] = null;?

          ? ??return obj;

          }

          但是不要濫用,不要每個對象使用后都用NULL。

          ?

          Item 6: 避免finalizer

          不要當作C++中的析構函數,正確的方法是放在finally中。

          ?

          ?

          Methods Common to All Objects

          ?

          Item 7: 當你覆蓋equals方法的時候一定要遵守general contact

          覆蓋equals的時候一定要加倍的小心,其實最好的辦法就是不覆蓋這個方法。比如在下面的情況下就可以不覆蓋

          ?? 1 這個類的每個實例都是唯一的,例如Thread

          ?? 2 如果你不關心這個類是否該提供一個測試邏輯相等的方法

          ?? 3 超類已經覆蓋了equals方法,并且它合適子類使用

          ?? 4 如果這個類是private或者是package-private的,并且你確信他不會被調用

          覆蓋時遵守的原則是

          必須與自身相等,對稱性A<->B,傳遞性,一致性如果不改變始終都是一致的結果,不能與NULL相等。

          ?

          Item 8: 當你覆蓋equals的時候必須覆蓋hashCode方法

          不這么做的話,有關hash-based的集合操作會出錯。

          契約:

          同一對象的hashCode返回相同的結果(equals比較屬性沒改變),如果equals相等,則hashCode相等,如果equals不等,則hashCode不必不等。

          ?

          ?

          Item 9: 總是覆蓋toString方法

          Object toString方法返回的形式是Class的類型加上@加上16進制的hashcode,不利于描述對象的信息。

          ?

          Item 10: 謹慎覆蓋clone()方法

          盡量不要實現,碰到deepcopy的問題。

          ?

          Item 11: 考慮實現覆蓋Comparable接口

          ?

          契約:傳遞性,x.compareTo(y)>0,y.compareTo(z)>0,x.compareTo(z)>0

          如果x.compareTo(y)0,則x.compareTo(z)y.compareTo(z)結果一致

          建議x.compareTo(y)0 x.equals(y)=true,但不要求。

          ?

          ?

          Classes and Interfaces

          ?

          Item 12: 把類和成員的可訪問范圍降到最低

          通常public類里不應該有public字段,除了常量,要注意常量應該是不可修改的。

          public class Con {

          public static final int[] data = {1,2,3};// it is bad

          public static final String hello = "world";

          public static final int i = 1;

          }

          ?

          Item 13: 偏愛不可修改的類

          5 個原則保證不可修改

          不提供可修改對象的方法,方法不可被覆蓋(final),所有字段是final,所有字段是private,確保外部不能訪問到類的可修改的組件

          好處

          可自由共享,線程安全

          ?

          Item 14: 優先考慮合成(復合),其次是繼承

          利用wrapper class,除非確實是is a的關系。

          ?

          ?

          Item 15: 如果要用繼承那么設計以及文檔都要有質量保證,否則就不要用繼承

          為了避免繼承帶來的問題,你必須提供精確的文檔來說明覆蓋相關方法可能出現的問題。

          在構造器內千萬不要調用可以被覆蓋的方法

          由于在Clone()或者序列化的時候非常類似構造器的功能,因此readObject()clone()方法內最好也不要包括能被覆蓋的方法。

          ?

          ?

          Item 16: 使用接口代替抽象類

          單重繼承

          ?

          Item 17: 接口只應該用來定義類型

          常量不應該放在接口中。

          ?

          Item 18: 優先考慮靜態內部類,而非非靜態內部類

          ?

          ?

          Substitutes for C Constructs

          ?

          Item 19: 用類代替結構

          ?

          Item 20: 用類繼承來代替聯合

          ?

          Item 21: 用類來代替enum結構

          ?

          Item 22: 用類和接口來代替函數指針

          ?

          ?

          Methods

          ?

          Item 23: 檢查參數的有效性

          ?

          Item 24: 需要時使用保護性拷貝

          ?

          Item 25: 謹慎設計方法的簽名

          命名,不要過分提供便利的方法,避免過長參數列表

          ?

          對于參數類型,優先使用接口而不是類

          謹慎的使用函數對象

          ?

          Item 26: 謹慎的使用重載

          ?

          Item 27: 返回零長度的數組而不是null

          ?

          Item 28: 為所有導出的API元素編寫文檔注釋

          當代碼能很好的說明問題時,可不寫注釋

          ?

          ?

          General Programming

          ?

          Item 29: 將局部變量的作用域最小化

          不易閱讀,在變量聲明的時候初始化,try-catch例外

          for 循環優于while循環,for完全獨立,重用變量名不會有任何問題

          for (int i=0,n=list.size(); i<n; i++) {

          ??? dosomething(list.get(i));

          }

          ?

          Item 30: 了解和使用庫

          ?

          Item 31: 如果想要知道精確的答案,就要避免使用doublefloat

          使用int,longBigDecimal

          ?

          Item 32: 如果其他類型更適合,則盡量避免使用字符串

          如枚舉

          ?

          Item 33: 了解字符串的連接功能

          使用StringBuffer代替String

          ?

          Item 34: 通過接口引用對象

          參數、返回值,將會給函數帶來很大的靈活

          ?

          Item 35: 接口優先于反射機制

          損失了編譯期的類型檢查的好處,性能上也會受損。

          ?

          Item 36: 謹慎的使用本地方法

          ?

          Item 37: 謹慎使用優化

          不要因為性能而犧牲合理的代碼結構

          ?

          Item 38: 遵守普遍接受的命名慣例

          ?

          ?

          Exceptions

          ?

          Item 39: 僅在異常情況下使用異常

          try {

          int i=0;

          while (true)

          a[i++].f();

          } catch (ArrayIndexOutOfBoundsException) {}

          利用異常終止循環,不要這樣濫用異常。

          一個良好的設計不應該依靠異常去控制流程

          ?

          Item 40: 可恢復狀態使用檢查異常(Exception),對編程錯誤使用運行期異常(RuntimeException)

          ?

          Item 41: 避免不必要的使用檢查異常

          可以先檢查是否有異常情況,而不是直接用try-catch控制程序流程

          ?

          Item 42: 盡量使用標準異常

          IllegalArgumentException 參數不合法,IllegalStateException狀態不合法

          NullPointerException 空指針,IndexOutOfBoundsException越界

          ?

          Item 43: 引發的異常要與抽象對應

          異常的分層,lower-level high-level

          ?

          Item 44: 提供每個方法所拋出的異常的文檔

          javadoc@throws標簽

          一般針對檢查異常

          ?

          Item 45: messages中記錄失敗捕獲的信息

          ?

          Item 46: 使失敗原子化

          即使方法調用失敗后,也要恢復對象的狀態成為調用方法前的狀態

          ?

          Item 47: 不要忽略異常

          不要catch塊內什么都不做

          ?

          ?

          Threads

          ?

          Item 48: 同步訪問共享可變的數據

          private static int nextSerialNumber = 0;

          // 需要同步

          public static int generateSerialNumber() {

          ???? return nextSerialNumber++;

          }

          public class StoppableThread extends Thread {

          ???? private boolean stopRequested = false;

          ???? public void run() {

          ???????? boolean done = false;

          ???????? while (!stopRequested() && !done) {

          ????????????? //dosth

          ???????? }

          ???? }

          ???? // 需要同步

          ???? public synchronized void requestStop() {

          ???????? stopRequested = true;

          ???? }

          ???? private synchronized boolean stopRequested() {

          ???????? return stopRequested;

          ???? }

          }

          ?

          Item 49: 避免過度使用同步

          性能的下降

          在同步塊里盡可能少的操作

          ?

          Item 50: 不要在循環外部調用wait

          一般習慣的方法

          synchronized (obj) {

          ???? while (<condition does not hold>)

          ???????? obj.wait();

          ???? //Perform action appropriate to condition

          }

          ?

          Item 51: 不要依賴線程調度器

          ?

          Item 52: 文檔化線程安全

          如果一個類支持線程安全的話,一定要文檔說明

          ?

          Item 53: 避免使用線程組

          ?

          ?

          Serialization

          ?

          Item 54: 謹慎實現Serializable

          表面簡單implements Serializable,實際上復雜

          如果實現了,那私有或包私有的屬性也會成為exported API的一部分,違背了隱藏內部實施細節的原則。

          serialVersionUID 屬性,如果代碼中不指定的話,系統會根據類名,實現接口名,成員名稱,生成一個

          即使添加一個很普通的方法,也會改變該值,這樣就失去兼容性。

          ?

          Item 55: 考慮使用自定義的序列化格式

          覆蓋writeObject()readObject()

          ?

          Item 56: 保護性地編寫readObject方法

          存在安全漏洞,反序列化

          ?

          Item 57: 必要時提供readResolve方法

          主站蜘蛛池模板: 黔江区| 玉龙| 青神县| 施秉县| 万宁市| 开江县| 牙克石市| 辰溪县| 峨边| 武冈市| 渑池县| 灵台县| 深州市| 锡林郭勒盟| 东明县| 凤山县| 昌乐县| 新余市| 卓资县| SHOW| 赤水市| 泰和县| 三原县| 临湘市| 山西省| 大关县| 大同县| 邯郸市| 洛宁县| 莱州市| 咸阳市| 肇源县| 饶平县| 沙雅县| 二连浩特市| 赞皇县| 桦南县| 平潭县| 虞城县| 海安县| 彰武县|