<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

    Practical Java讀書筆記

    Posted on 2006-08-30 17:50 繁星滿空 閱讀(492) 評論(0)  編輯  收藏 所屬分類: Java

    作者簡介:Peter HaggarIBM在北卡羅來納州的Research Triangle Park的一名高級軟件工程師,他發表了無數篇關于 Java 編程的文章。他有著廣泛的編程經驗,曾致力于開發工具、類庫和操作系統的相關工作。Peter IBM從事新興因特網技術方面的工作,目前主要從事有關高性能Web服務方面的工作。Peter經常在很多業界會議上作為技術發言人就 Java 技術發表言論。他已經為IBM工作了15年多,并獲得了Clarkson University的計算機科學學士學位。

    ?

    本書匯集了Java編程實踐方面的建議、忠告、范例和討論,本書的組織是一個個獨立的課程,每個課程稱為實踐(PRAXIS),用以討論特定主題,每個實踐按各自獨立的方式撰寫。本身詳細分析了某些設計和編程方面的問題,挑選的依據是編程實踐上的有效和高效。Java最被人抱怨的一點是性能,因此本書以最大的篇幅討論這一主題,使Java代碼運行得更高效。


    General Techniques


    ?

    PRAXIS1: 引數以by value方式而非by reference方式傳遞

    所有Java對象都通過object reference被訪問,常見的一個誤解是javaby reference方式傳遞引數,

    事實上所有引數都以by value方式傳遞。

    ?

    比如int參數,在函數內修改了,在調用后并沒有修改

    object則不是這樣,函數內修改了,調用后也是修改的,若不想這樣,可以把object改為不可變的或拷貝object

    ?

    PRAXIS2: 對不變的dataobject references使用final

    為了讓dataobject reference成為不變量(常數),請使用final。注意,final僅僅令object reference

    自身成為不變量,并不限制它所指對象的改變。

    ?

    PRAXIS3: 缺省情況下所有non-static函數都可被覆蓋

    缺省情況下,所以non-static函數都可以被subclass覆蓋,但如果加上關鍵字final,便可防止被subclass覆蓋。

    聲明某個類為final,就表示這個類的所有函數都是final的,可以阻止它派生子類。

    ?

    PRAXIS4: arraysVectors之間慎重選擇

    arrays vectors是常見的容器類(storage classes)。選用它們之前應該先了解它們的功用和特性。

    ?

    如果超出了array的大小,會報數組越界異常,基本類型的array會自動為數組內的元素賦默認值,而對象數組則是null。而vector長度會自動增長,vector.size()返回的元素的數量,不是固定值,vector的內部實現是array實現的,vector只能容納對象。

    一般來說,array速度更快。

    ?

    PRAXIS5: 多態優于instanceof

    instanceof 的許多用途可以因為改用多態而消失,使用多態,代碼將更清晰、更易于擴展和維護。

    ?

    PRAXIS6: 必要時才使用instanceof

    有時我們無法回避使用instanceof。我們應該了解什么情況下必須使用它。

    ?

    PRAXIS7: 一旦不再需要object references,就將它設為null

    不要忽視內存可能帶來的問題,盡管有了垃圾回收機制,你仍然需要關注你的代碼如何運用內存,如果能夠領悟垃圾回收和內存運用細節,你就能夠更好的知道何時應該將object references設為null,那將導致高效的代碼。



    Objects and Equality


    ?

    PRAXIS8: 區分reference typeprimitive type

    Java 是面向對象語言,但其操控的東西并非都是對象(objects)。理解reference typeprimitive types之間的差異,及它們在JVM中的表述,會使你在運用它們時得以做出明智的選擇。

    ?

    PRAXIS9: 區分==equals()

    == 用來測試基本型別的相等性,亦可判定兩個object references是否指向同一個對象,但若要測試

    values (值)或semantic(語義)相等,應使用equals()。

    ?

    PRAXIS10: 不要依賴equals()的缺省實現

    不要不假思索的認定一個class總是會正確的實現出equals(),此外,java.lang.Object提供的equals()大多數時候并非進行你想要的比較。

    ?

    PRAXIS11: 實現equals()時必須深思熟慮

    如果某個class所生的兩個對象“即使不占用相同的內存空間,也被視為邏輯上相等”,那么就該為這個class提供一個equals()。

    ?

    PRAXIS12: 實現equals()時優先考慮使用getClass()

    實現equals()時請優先考慮采用getClass()。畢竟,“隸屬同一個class下的對象才得被視為相等”是正確實現equals()的一個簡明方案。

    ?

    惟有相同class所產生的對象才可以被視為相等,可以只比較某些關鍵屬性。

    ?

    PRAXIS13: 調用super.equals()以喚起base class的相關行為

    任何base class(除了java.lang.Object)如果實現equals(),其derived class都應該調用super.equals()

    ?

    PRAXIS14: equals()函數中謹慎使用instanceof

    惟有當你考慮允許“一個derived class對象可以相等于其base class對象”時,才在equals()中使用instanceof。使用這項技術前請先弄清楚其影響。

    ?

    PRAXIS15: 實現equals()時需遵循某些規則

    撰寫equals()并非那么直觀,如果想要恰當實現出equals(),請遵循某些規則。

    ?

    1. 如果某個class的兩個對象即使占據不同的內存空間,也可被視為“邏輯上相等”的話,那么你得為這個class提供一個equals()。

    2. 請檢查是否等于this。

    3. 比較這個class中的相關屬性,以判斷兩個對象是否相等。

    4. 如果有java.lang.Object以外的任何base class實現了equals(),那么就應該調用super.equals()




    Exception Handling


    ?

    PRAXIS16: 認識“異??刂屏鳌保?span lang="EN-US">exception control flow)機制

    了解異常控制流程細節,了解這些細微之處有助于你回避問題。

    ?

    PRAXIS17: 不要忽略異常

    一旦異常出現卻沒有被捕獲,拋出異常的那個線程就會中止運行,是的,異常意味錯誤,永遠不要忽略它。

    ?

    PRAXIS18: 不要隱藏異常

    如果處理異常期間又從catchfinally區段拋出異常,原先的異常會因而被隱藏起來,一旦發生這樣的事情,就會丟失錯誤信息,你應當撰寫專門負責處理這種情形的代碼,將所有異常回傳給調用者。

    ?

    只有一個異??梢詡鞑サ酵饨?,可以把所有的異常加入到一個vector內。

    ?

    PRAXIS19: 理解throws子句的缺點

    將一個異常加入某函數的throws子句,會影響該函數的所有調用者。

    ?

    PRAXIS20: 細致而全面的理解throws子句

    任何函數的throws子句應當列出它所傳播的所有異常,包括衍生異常型別(derived exception types)。

    ?

    覆蓋一個方法時,throws的異常受到約束

    要么不拋出異常,要么和被覆蓋方法一樣類型的異常,要么是被覆蓋方法異常的派生異常。

    ?

    PRAXIS21: 使用finally避免資源泄漏

    不要忽視內存以外的資源,垃圾回收機制不會替你釋放它們,請使用finally確保內存以外的資源被釋放。

    ?

    PRAXIS22: 不要從try塊中返回

    不要從try區段中發出return語句,因為這個函數未必會立即從那兒返回,如果存在finally區段,它就會被運行起來并可能改變回傳值。

    ?

    PRAXIS23: try/catch代碼塊置于循環外

    撰寫含有異常處理的循環時,請將trycatch區段置于循環外部,在某些實現版本上,這會產生更快的運行代碼。

    ?

    PRAXIS24: 不要將異常用于流程控制

    請將異常用于預期行為之外的情況,不要以異常來控制流程,請采用標準的語言流程構件,這樣的流程表達會更清晰更高效。

    ?

    PRAXIS25: 不要每逢出錯就使用異常

    只有面對程序行為可能出乎意料的情況下才使用異常,“預期中的行為”應使用返回代碼來處理。

    ?

    PRAXIS26: 在構造函數中拋出異常

    盡管構造函數并非函數(method),因而不能回傳一個值,但構造函數有可能失敗,如果它們失敗了,請拋出一個異常。

    ?

    PRAXIS27: 拋出異常之前先將對象恢復為有效狀態(valid state

    拋出異常很容易,困難的是“將異常所引發的傷害減到最小”,拋出異常前,應確?!叭绻惓1惶幚砗?,流程再次進入拋出異常的那個函數中,該函數可以成功完成”。




    Performance


    ?

    PRAXIS28: 先把焦點放在設計、數據結構和算法身上

    java帶來最大性能提升的辦法就是:在設計和算法中使用與語言無關的技術,因此,首先請將你的精力集中在這上面。

    ?

    PRAXIS29: 不要依賴編譯期的優化技術

    java編譯器生成的代碼,通常不會比你自己撰寫的更好,別指望編譯器能夠多么優化你的源碼。

    ?

    PRAXIS30: 理解運行期的代碼優化技術

    Java 對性能的大部分努力都圍繞著“運行期優化”展開,這種做法有利無弊。

    ?

    PRAXIS31: 如欲進行字符串的連接,StringBuffer優于String

    對于字符串的連接,StringBuffer要比String快許多倍。

    ?

    PRAXIS32: 將對象的創建成本降至最小

    在許多面向對象系統中,“創建對象”意味著高昂的成本,了解成本所在,以及了解“加速對象創建速度”的技術,都可以導致更快速的程序。

    ?

    PRAXIS33: 謹防未使用的對象

    非必要別產生對象,否則會減慢你的程序速度。

    ?

    PRAXIS34: 將同步(synchronization)減至最低

    聲明synchronized函數或synchronized區段,會顯著降低性能,應該只在對象有所需要時才使用同步機制。

    ?

    PRAXIS35: 盡可能使用stack變量

    stack 變量為JVM提供了更高效的byte code指令序列,所以在循環內重復訪問static變量或instance變量時,應當將它們暫時存儲于stack變量中,以便獲得更快的運行速度。

    ?

    PRAXIS36: 使用static、finalprivate函數以促成inlining

    以方法體替換方法調用,會導致更快速的程序,如果要令函數為inline,必須先聲明它們為staticfinalprivate

    ?

    PRAXIS37:instance 變量的初始化一次就好

    由于所有static變量和instance變量都會自動獲得缺省值,所以不必重新將它們設為缺省值。

    ?

    PRAXIS38: 使用基本類型(primitive types)使代碼更快更小

    使用基本類型,比使用其包裝類,產生的代碼又小又快。

    ?

    PRAXIS39: 不要使用EnumerationIterator來遍歷Vector

    遍歷Vector時,請使用get()函數而非EnumerationIterator。這樣做會導致更少的函數調用,意味程序速度更快。

    ?

    PRAXIS40: 使用System.arraycopy()來復制arrays

    這個是本機(native)函數,速度更快。

    ?

    PRAXIS41: 優先使用array,然后才考慮VectorArrayList

    如果你需要Vector的功能但不需要它的同步特性,可改用ArrayList

    ?

    PRAXIS42: 盡可能復用(reuse)對象

    復用現有對象,幾乎總是比創建新對象更劃算。

    ?

    PRAXIS43: 使用延遲求值(lazy evaluation

    如果某個成本高貴的計算并非一定必要,就盡量少做,使用懶加載技術避免那些永遠不需要的工作。

    ?

    PRAXIS44: 以手工方式將代碼優化

    由于Java編譯器在優化方面的作為甚少,為了生成最佳byte code,請以手工方式將你的源碼優化。

    ?

    PRAXIS45: 編譯為本機代碼(native code

    編譯為本機代碼,通常可以獲得運行速度更快的代碼,但你卻因此必須在各種不同的本機方案中取舍。

    ?



    Multithreading


    ?

    PRAXIS46: 面對instance函數,synchronized鎖定的是對象(object)而非函數(method)或代碼

    關鍵字synchronized鎖定的是對象,而非函數或代碼,一個函數或程序區段被聲明為synchronized,并不意味同一時刻只能由一個線程運行它。

    ?

    PRAXIS47: 弄清楚synchronized statics函數與synchronized instance函數之間的差異

    兩個函數被聲明為synchronized,并不就意味它們是“多線程安全”,對instance函數或object reference同步化,與對static函數或class literal(字面常數)同步化相比,得到的lock全然不同。

    ?

    PRAXIS48: private數據(field+相應的訪問函數(accessor)替換public/protected數據

    如果沒有適當保護你的數據,用戶便有機會繞過你的同步機制。

    ?

    PRAXIS49: 避免無謂的同步控制

    一般情況下請不要同步化所有函數,同步化不僅造成程序緩慢,并且喪失了并發(concurrency)的可能,

    請采用“單對象多鎖”技術以允許更多并發動作。

    ?

    PRAXIS50: 訪問共享變量時請使用synchronizedvolatile

    不可切割(原子化,atomic)操作并非意味“多線程安全”,JVM實現品被允許在私有內存中保留變量的工作副本,這可能會產生陳舊數據,為避免這個問題,請使用同步化機制或將變量聲明為volatile

    ?

    PRAXIS51: 在單一操作中鎖定所有用到的對象

    同步化某一函數,并不一定就會使其成為“多線程安全”,如果synchronized函數操控著多個函數,而它們并不都是此函數所屬classprivate instance data,那么你必須對這些對象自身也進行同步化。

    ?

    PRAXIS52: 以固定而全局性的順序取得多個locks,以避免死鎖(deadlock

    當你同步化多個對象,請以固定、全局性的順序獲得locks,以避免死鎖。

    ?

    PRAXIS53: 優先使用notifyAll()而非notify()

    notify() 只喚醒一個線程,要想喚醒多個線程,請使用notifyAll()

    ?

    PRAXIS54: 針對wait()notifyAll()使用旋鎖(spin locks

    當你等待條件變量時,請總是使用旋鎖確保正確結果。

    ?

    PRAXIS55: 使用wait()notifyAll()替換輪詢循環(polling loops

    將所有polling loops替換為使用wait()、notify()notifyAll()spin locks(旋鎖),spin locks直觀而高效,polling loops則慢很多倍。

    ?

    PRAXIS56: 不要對上鎖對象(locked object)的object reference重新賦值

    當一個對象被鎖定,有可能其他線程會因同一個object lock而受阻(blocked),假如你對上鎖對象的object reference重新賦值,其他線程內懸而未決的那些locks將不再有意義。

    ?

    PRAXIS57: 不要調用stop()suspend()

    不要調用stop()suspend(),因為它們可能導致數據內部混亂,甚至引發死鎖。

    ?

    PRAXIS58: 通過線程之間的協作來中止線程

    你不應該調用stop(),如欲安全地停止線程,必須要求它們相互協作,才能姿態優雅的中止。

    ?



    Classes and Interfaces


    ?

    PRAXIS59: 運用interfaces支持多重繼承

    當你想要支持interface的單一繼承或多重繼承,或想要實現一個標識型的interface時,請使用interfaces

    ?

    PRAXIS60: 避免interfaces中的函數發生沖突

    沒有任何辦法能夠阻止兩個interfaces使用同名的常數和函數,為了避免可能的沖突,應當小心命名常數和函數。

    ?

    PRAXIS61: 如需提供部分實現(partial implementation),請使用抽象類(abstract classes

    使用abstract class來為一個class提供部分實現,這些實現很可能對derived class是共通的。

    ?

    PRAXIS62: 區分interface、abstract classconcrete class

    一旦正確理解interface、abstract classconcrete class的差異,你就可以在設計是編碼時做出正確的選擇。

    ?

    PRAXIS63: 謹慎定義和實現不可變類(immutable classes

    如果你希望對象內容永遠不被改動,請使用不可變對象(immutable object),這種對象自動擁有“多線程安全性”。

    ?

    PRAXIS64: 欲傳遞或接收可變對象(mutable objects)的object references時,請使用clone()

    為了保證immutable objects,你必須在傳入和回傳它們時對它們施行clone()。

    ?

    PRAXIS65: 使用繼承或委托(delegation)來定義不可變類(immutable classes

    使用immutable interface、common interfacebase class,或是immutable delegation classes,來定義immutable classes。

    ?

    PRAXIS66: 實現clone()時記得調用super.clone()

    當你實現一個clone(),總是應該調用super.clone()以確保產生正確的對象。

    ?

    PRAXIS67: 別只依靠finalize()清理non-memory(內存之外)的資源

    你不能保證finalize()是否被調用,以及何時被調用,因此,請專門實現一個public函數來釋放內存以外的資源。

    ?

    PRAXIS68: 在構造函數內調用non-final函數時要小心

    如果一個non-final函數被某個derived class覆蓋,在構造函數中調用這個函數可能會導致不可預期的結果。

    ?

    主站蜘蛛池模板: 99久热只有精品视频免费观看17| 香蕉免费看一区二区三区| 久操视频免费观看| 亚洲中文字幕无码久久精品1| 黄色一级视频免费观看| 亚洲成av人片一区二区三区 | 亚洲阿v天堂在线| 男女拍拍拍免费视频网站| 亚洲精品国产精品乱码不卞| 一区二区在线免费视频| 亚洲情a成黄在线观看| 国产免费人成视频尤勿视频| 国产亚洲AV手机在线观看| a级毛片毛片免费观看久潮喷| 亚洲国产精品无码久久一线| 99在线免费观看视频| 亚洲大香伊人蕉在人依线| av无码国产在线看免费网站| 亚洲私人无码综合久久网| 国产老女人精品免费视频| 日韩在线一区二区三区免费视频| 亚洲精品综合久久| 国产免费拔擦拔擦8X高清在线人| 久久久亚洲欧洲日产国码是AV| 免费h片在线观看网址最新| 亚洲精品日韩一区二区小说| 免费一级毛片不卡在线播放| 在线观看免费黄网站| 亚洲老熟女@TubeumTV| 精品久久久久久久免费加勒比| 一级毛片在线免费播放| 久久久久久亚洲精品中文字幕| 青娱乐免费在线视频| 日韩成人精品日本亚洲| 亚洲码国产精品高潮在线| 日本成年免费网站| 免费人成动漫在线播放r18| 亚洲精选在线观看| 日韩免费电影在线观看| a毛片在线还看免费网站| ass亚洲**毛茸茸pics|