Num1:for-each迴圈優先於傳統的for迴圈
java1.5版本釋出之前的做法:
for(int i=0;i<a.length;i++){
doSomething(a[i]);
}
java1.5發行版本中引入的for-each迴圈,通過完全隱藏迭代器或索引變數,避免了混亂和出錯的可能。
示例程式碼:
enum Suit {
CLUB, DIAMOND, HEART, SPADE
}
enum Rank {
ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING
}
class Card {
final Suit suit;
final Rank rank;
Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
}
public class NestedIteration {
public static void main(String[] args) {
Collection<Suit> suits = Arrays.asList(Suit.values());
Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<Card>();
for (Iterator<Suit> i = suits.iterator(); i.hasNext();)
for (Iterator<Rank> j = ranks.iterator(); j.hasNext();)
deck.add(new Card(i.next(), j.next()));
// Preferred idiom for nested iteration on collections and arrays
// for (Suit suit : suits)
// for (Rank rank : ranks)
// deck.add(new Card(suit, rank));
}
}
總之,for-each迴圈在簡潔性和預防Bug方面有著傳統的for迴圈無法比擬的優勢,並且沒有效能損失。應該儘可能地使用for-each迴圈。遺憾的是,有三種常見的情況無法使用for-each迴圈:
- 過濾:如果需要遍歷集合,並刪除選定的元素,就需要使用顯式的迭代器,以便可以呼叫它的remove方法。
- 轉換:如果需要遍歷列表或者陣列,並取代它部分或者全部的元素值,就需要列表迭代器或者陣列索引,以便設定元素的值。
- 平行迭代:如果需要並行地遍歷多個集合,就需要顯式地控制迭代器或者索引變數,以便所有迭代器或者索引變數都可以得到同步前移。
Num2:如果需要精確的答案,請避免使用float和double
float
,double
型別尤其不適合用於貨幣計算。
Num3:基本型別優先於裝箱基本型別
自動裝箱減少了使用裝箱基本型別的繁瑣性,但是並沒有減少它的風險。
Num4:如果其他型別更適合,則儘量避免使用字串
- 字串不適合代替其他的值型別
- 字串不適合代替列舉型別
- 字串不適合代替聚集型別
- 字串也不適合代替能力表
Num5:當心字串連線的效能
字串連線操作符(+)是把多個字串合併一個字串的便利途徑。為連線n個字串而重複地使用字串連線操作符,需要n的平方級的時間。
不要使用字串連線操作符來合併多個字串,除非效能無關緊要。相反,應該使用StringBuilder
的append
方法。
Num6:通過介面引用物件
一般來講,應該優先使用介面而不是類來引用物件。
- 如果有合適的介面型別存在,那麼對於引數、返回值、變數或域來說,就都應該使用介面型別進行宣告。
- 如果沒有合適的介面存在,完全可以用類而不是介面來引用物件。
如果你養成了用介面的作為型別的習慣,你的程式將會更加靈活。