1. 程式人生 > >Effective Java讀書筆記四:通用程式設計

Effective Java讀書筆記四:通用程式設計

第45條:將區域性變數的作用域最小化

  1. 在第一次使用變數時的地方宣告;
  2. 幾乎每個區域性變數的宣告都應該包含一個初始表示式;
  3. 如果在終止迴圈之後不需要迴圈變數的內容,for迴圈優於while迴圈。(for迴圈比while迴圈還有個優勢:更簡潔,增強可讀性)
for(int i =0,n = expensiveComputation(); i < n; i ++){
  doSomething(i);
}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

關於這種做法要關注的一點是,它具有兩個迴圈變數:i和n,兩者具有相同的作用域。第二個變數n被採用來儲存第一個變數的極限值,從而避免在每次迭代中執行冗餘計算的開銷。通常,如果迴圈測試中涉及方法呼叫,它可以保證每次迭代都會返回同樣的結果,就應該使用這種做法。

第46條:for-each迴圈優先於傳統的for迴圈

1.對於多個集合進行巢狀迭代時,for-each迴圈優勢更明顯. 
2.for-each迴圈不僅可以遍歷集合、陣列和列舉,還可以遍歷任何實現Iterable介面的物件。 
3.無法使用for-each迴圈的情況: 
  過濾–如果需要在集合上遍歷且移去選定的元素,就要使用顯式的迭代,並呼叫它的remove方法。 
  轉換–如果需要在list或陣列上遍歷且要替換部分或所有的元素值,則需要list的迭代器或陣列的索引去設定這些值。 
  平行迭代–如果需要並行的遍歷多個集合,則需要顯式的控制迭代器或索引變數,以便所有的迭代器或索引能協同推進。

第47條:瞭解和使用標準類庫

1、通過使用標準類庫,可以充分利用這些編寫標準類庫專家的知識,以及在你之前的其他人的使用經驗。 
2、不必將你的時間浪費在與你工作基本無關的問題上。與大多數程式設計師一樣,你應該將你的時間放在你的應用研發上,而不是底層細節上。 
3、無需你的努力,標準類庫的效能會隨著時間的推遲而改善。因為類庫被許多人使用,也因為類庫以工作標準基準被使用,所以類庫的供應商有著強烈的動機讓類庫執行得更快。 
4、可以使你的程式碼融於主流中,這種類碼更易讀,更易維護,更易被大多數開發者重用。

第48條:如果需要精確的答案,請避免使用float和double

1、float和double型別尤其不適合用於貨幣計算 
2、可以使用bigDecimal、int或者long進行貨幣計算(BigDecimal不方便而且慢,如果數值範圍沒有超過9位十進位制數字,就可以使用int;如果不超過18位數字,就可以使用long;如果可能超過18位,就必須使用BigDecimal)

第49條:基本型別優先於裝箱基本型別

基本型別和裝箱基本型別的區別: 
1.基本型別只有值,而裝箱基本型別則具有與它們的值不同的同一性。 
2.基本型別只有功能完備的至,而每個裝箱基本型別除了它對應基本型別的所有功能值之外,還有個非功能值:null。 
3.基本型別通常比裝箱基本型別更節省時間和空間。

裝箱基本型別的合理用處: 
1.作為集合中的元素、鍵和值。你不能將基本型別放在集合中,因此必須使用裝箱基本型別。 
2.在引數化型別中,必須使用裝箱基本型別作為型別引數,因為Java不允許使用基本型別。 
3.在進行反射的方法呼叫時,必須使用裝箱基本型別。

當可以選擇的時候,基本型別要優於裝箱基本型別。基本型別更加簡單,也更加快速。如果必須使用裝箱基本型別,要特別小心!自動裝箱減少了使用裝箱基本型別的繁瑣性,但是並沒有減少它的風險。當程式使用==操作符比較兩個裝箱基本型別時,它做了個同一性比較,這幾乎肯定不是你所希望的。當程式進行涉及裝箱和拆箱基本型別的混合計算時,它會進行拆箱,當程式進行拆箱時,會丟擲NullPointerException異常。最後,當程式裝箱了基本型別值時,會導致高開銷和不必要的物件建立。

第50條:如果其他型別更適合,則儘量避免使用字串

  1. 字串不適合代替其他的值型別 
    當一段資料從檔案、網路、或者鍵盤裝置,進入到程式之後,它通常以字串的形式存在。有一種自然的傾向是讓它繼續保留這種形式,但是,只有當這段資料本質上確實是文字資訊時,這種想法才是合理的。
  2. 字串不適合替代列舉型別 
    列舉型別比字串更加適合用來表示列舉型別的常量
  3. 字串不適合代替聚集型別 
    如果一個實體有多個元件,用一個字串來表示這個實體通常是不恰當的
String compoundKey = className + "#" + i.next();
  • 1
  • 1

這種方法有許多缺點。如果用來分割域的字串也出現在某個域中,結果就會出現混亂。為了訪問單獨的域,必須解析該字串,這個過程非常慢,也很繁瑣,還容易出錯。你無法提供equals、toString或者compareTo方法,只好被迫幾首String提供的行為。更好的做法是,簡單的編寫一個類來描述這個資料集,通常是一個私有的靜態成員類。 
4. 字串不適合代替能力表 有時候,字串被用於某種功能進行授權訪問。

如果可以使用更加合適的資料型別,或者可以編寫更加合適的資料型別,就應該避免用字串表示物件。若使用不當,字串會比較其他型別更急笨拙、更加不靈活、速度更慢,也更容易出錯。經常被錯誤的用字元來代替的型別包括基本型別、列舉型別和聚集型別。

第51條:當心字串連線的效能

  1. 為連線n個字串而重複使用字串連線符(+),需要n的平方級時間。這是由於字串不可變,當兩個字串被連線在一起時,他們的內容都要被拷貝。
  2. 當我們的程式需要效能的時候,不要使用字串連線操作符(+)來合併多個字串 。最好使用StringBuilder的append方法。
  3. StringBuilder類是非執行緒,StringBuffer是執行緒安全的

第52條:通過介面引用物件

1、優先使用介面而不是類來引用物件。 
如果有合適的介面型別存在,那麼對引數、返回值、變數和域來說,就應該使用介面型別進行宣告。 
只有當利用構造器建立某個物件的時候才真正需要引用這個物件的類

List<Subscriber> subscribers = new ArrayList<Subscriber>();
  • 1
  • 1

2、 如果沒有合適的介面存在,完全可以用類而不是介面來引用物件,有三種情況:

  • 具體類沒有相關聯的介面,例如:Random類;
  • 物件屬於基於類的框架,例如TimerTask抽象類;
  • 類實現了介面,但它提供了介面中不存在的而外方法,例如:LinkedHashMap,如果程式依賴這些額外的方法,這種類就應該只被用來引用它的例項。

第53條:介面優先於反射機制

1、反射機制(reflection)允許一個類使用另一個類,即使當前者被編譯的時候還根本不存在。然而這樣做要付出代價:

  • 喪失了編譯時型別檢查的好處;
  • 執行反射訪問所需要的程式碼非常笨拙和冗長;
  • 效能損失。反射方法的呼叫比普通方法呼叫慢了許多。
  • 反射功能只是在設計時被用到,普通應用程式執行時不應該以反射方式訪問物件。

2、反射機制的作用: 
對於有些程式,它們必須用到在編譯時無法獲取的類,但在編譯時存在適當的介面或者超類,通過它們可以引用這個類。如果是這種情況,就可以以反射的方式建立例項,然後通過它們的介面或者超類,以正常的方式訪問這些例項。如果適當的構造器不需要任何引數,那就不需要使用java.lang.reflect包,採用Class.newInstace方法就可以了。

第54條:謹慎地使用本地方法

使用本地方法的重要缺點:本地語言不是安全的;本地語言是與平臺相關的。

第55條:謹慎地進行優化

不用費力去編寫快速的程式–應該努力編寫更好的程式,速度自然會隨著而來。

第56條:遵守普通接受的命名慣例

可以參考各大公司的開發手冊中的命名規範

from: http://blog.csdn.net/jiankunking/article/details/54863890?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io