書籍
《Practical Java 中文版》 03版 侯捷、劉永丹譯
本書和《Effective Java》,對前述重要而基礎的技術細微處有著詳盡、深刻、實用的介紹、剖析和范例,又以獨立條款之姿展現,在內容的紮實度、可讀性及易讀性上的表現均十分良好。
本書圍繞Java編程中遇到的實際問題展開。可以說書中所列專題正是那些令許多Java程序員困惑不已的FAQ。作者擅長采用恰如其分的示例來闡釋問題,以平時的語言娓娓道出中肯的建議。這些建議往往一語中的,能直接融入編程工作中,可見它們確實是出自作者從實踐中獲得的真知灼見。
正文
註意:條目和用語可能與書籍有所出入,但盡量保持原樣加一些自己的理解。
一、一般技術
1. Java唯一一種參數傳遞機制:by value(傳值)。
備註:當參數為對象時,以傳值方式傳遞對象的引用。(個人理解:傳遞指針的拷貝)
2. 對不變的data和object references使用final
備註:當聲明一個對象為final時,不能改變其指向,但能改變其對象的值。
3. 缺省情況下所有非私有(non-private)、非靜態(non-static)函數都可被覆寫。
3.1 如果函數不想被子類覆寫,將函數聲明為final即可。
3.2 如果類不想被子類覆寫,將類聲明為final即可,從而禁止覆寫該類所有函數。還能提高性能。
4. 在數組和Vectors之間慎重選擇。
數組 Vector
存儲數據類型 基本類型、引用類型 引用類型
元素默認值 Yes No
自動改變大小 固定不變 動態增長
速度快 Yes No
備註: Vector內部實際是以數組實現的。
5. 多態優於instanceof,必要時才使用instanceof。
備註:例如從父類轉型為派生類時,需要使用instanceof。
6. 一旦不需要的對象引用,就將它設為null。
備註:如果局部變量的引用使用完離函數結束前還需要執行較大代碼,可在使用完後設置為null,以便或許能使其在垃圾回收器下次運行時被回收。
二、 對象與相等性
1. 區別 == 和 equals()
備註:請使用 == 測試兩個基本類型是否完全相同,或測試兩個對象引用是否指向同一個對象;使用equals()比較兩個對象的內容是否相等。
2. 不要依賴equals()缺省實現
備註:所有Java對象都隱含繼承瞭java.lang.Object,默認的equals()隻是檢查對象引用是否指向同一個對象。
3. 實現equals()建議:
3.1 請檢查是否等於this
備註:測試是否指向同一個對象
3.2 優先考慮使用getClass()
備註:getClass()返回某個對象的運行期類(runtime class)。確保隻有相同class所產生的對象才有機會被視為相等。范例:
public class Base {
@Override
public boolean equals(Object obj) {
if(obj != null && getClass() == obj.getClass()){
//繼續比較相等性或直接返回true
}
return false;
}
}
3.3 調用super.equals()喚起父類的相關行為
備註:當你為一個派生類撰寫equals()時,你必須檢查除java.lang.Object之外所有父類,看看它們是否都實現瞭equals()。如果有,那麼一定要調用super.equals()。
3.4 在equals()函數中謹慎使用instanceof
備註:如果允許派生類和父類進行比較,可能要采用instanceof(getClass()會恒返回false)。註意instanceof類似於is-a語義,需要註意位置,即(子類 instanceof 父類 -> 返回true;反之為false)。
三、 異常處理
1. 認識異常流程機制
備註:try區段 -> [catch捕獲區段][可選] -> finally終結區段。
2. 處理異常
如果異常產生卻未被捕獲,發生異常的線程將中斷。處理異常:
a). 捕獲並處理它,防止進一步傳播。
b). 捕獲並拋出一個新的異常給調用端。
備註:應確保新拋出的異常包含原異常相關信息,以保證不丟失重要信息。
c). 不捕獲,任其傳播給調用端。
輸出錯誤信息:
a). 日志文件記錄曾經發生過的異常
b). 輸出異常
輸出到標準錯誤串流:如e.printStackTrace()。
3. 防止出現異常覆蓋
備註:如果在catch或finally區段又拋出瞭未捕獲的異常,新的異常將覆蓋try拋出的異常,隻有一個異常可被傳播到調用段。
4. throws子句
備註:提供throws子句的用意在於,提醒函數調用者,告知可能發生的異常。編譯器會強迫調用端捕捉這些被列出的異常,所以不要再開發周期的最後才添加。
如果覆寫對象(某個父類函數)沒有拋出任何異常,那麼覆寫函數因為增加瞭代碼而引發異常,那麼你必須在新函數中捕捉異常並處理。
5. 使用finally避免資源泄漏
備註:finally區段代碼無論是否發生異常都將執行,尤其適合維護對象內部狀態和清理non-memory資源。
6. 使用建議:
a). 不要從try區段執行return、break或continue語句離開try區段
備註:如果try區段和finally區段都return 數據,將返回finally區段return的數據。
b). 將try/catch區段置於循環之外
備註:異常對代碼性能產生負面影響
c). 不要將異常用於流程控制
d). 在構造函數中拋出異常
e). 拋出異常之前將對象恢復為有效狀態
備註:考慮下次執行這段代碼時會發生什麼事情,代碼是否還能正常運行。
結束
預計本系列前幾篇文章為《Practical Java》和《Effective Java》的讀書筆記,後續內容還在規劃當中,也歡迎大傢把感興趣的內容反饋給我作為潛在的系列文章。
摘自 農民伯伯