【軟件構造】期末知識點

【考點 Equals】

  • ==是引用等價性 ;而equals()是對象等價性。 
    • == 比較的是索引。更準確的說,它測試的是指向相等(referential equality)。若是兩個索引指向同一塊存儲區域,那它們就是==的。對於咱們以前提到過的快照圖來講,==就意味着它們的箭頭指向同一個對象。
    • equals()操做比較的是對象的內容,換句話說,它測試的是對象值相等(object equality)。e在每個ADT中,quals操做必須合理定義。
  • 基本數據類型,也稱原始數據類型。byte,short,char,int,long,float,double,boolean 
    • 他們之間的比較,應用雙等號(==),比較的是他們的值。 
  • 複合數據類型(類) 
    • 當他們用(==)進行比較的時候,比較的是他們在內存中的存放地址,因此,除非是同一個new出來的對象,他們的比較後的結果爲true,不然比較後結果爲false。
    • JAVA當中全部的類都是繼承於Object這個基類的,在Object中的基類中定義了一個equals的方法,這個方法的初始行爲是比較對象的內存地址,但在一些類庫當中這個方法被覆蓋掉了,如String,Integer,Date在這些類當中equals有其自身的實現,而再也不是比較類在堆內存中的存放地址了。 
    • 對於複合數據類型之間進行equals比較,在沒有覆寫equals方法的狀況下,他們之間的比較仍是基於他們在內存中的存放位置的地址值的,由於Object的equals方法也是用雙等號(==)進行比較的,因此比較後的結果跟雙等號(==)的結果相同。
  • HahCode:Java中的hashCode方法就是根據必定的規則將與對象相關的信息(好比對象的存儲地址,對象的字段等)映射成一個數值,這個數值稱做爲散列值。

  當咱們當向集合中插入對象時,就可使用hashcode,先調用這個對象的hashCode方法,獲得對應的hashcode值,實際上在HashMap的具體實現中會用一個table保存已經存進去的對象的hashcode值,若是table中沒有該hashcode值,它就能夠直接存進去,不用再進行任何比較了;若是存在該hashcode值, 就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址,因此這裏存在一個衝突解決的問題,這樣一來實際調用equals方法的次數就大大下降了。html

 

【考點 函數規約】 requires與effects

聲明式規約更有價值 ; 內部實現的細節不在規約裏呈現,而放在代碼實現體內部註釋裏呈現,例:java

static String join(String delimiter, String[] elements) effects: returns concatenation of elements in order, with delimiter inserted between each pair of adjacent elements // Declarative specs

 

更強的規約包括更輕鬆的前置條件和更嚴格的後置條件;程序員

方法前的註釋也是一種規約,但需人工斷定其是否知足。算法

  • 參數由@param 描述
  • 子句和結果用 @return 和 @ throws子句 描述
  • 儘量的將前置條件放在 @param 中
  • 儘量的將後置條件放在 @return 和 @throws 中

 

 

【考點 ADT的四種類型】

  • Creators(構造器):
    • 建立某個類型的新對象,⼀個建立者可能會接受⼀個對象做爲參數,可是這個對象的類型不能是它建立對象對應的類型。可能實現爲構造函數或靜態函數。(一般稱爲工廠方法)
    • t* ->  T
    • 栗子:Integer.valueOf(Object  obj):object → integer
  • Producers(生產器):
    • 經過接受同類型的對象建立新的對象。
    • T+ , t* -> T
    • 栗子:String.concat( )  :String x String → String
  • Observers(觀察器):
    • 獲取抽象類型的對象而後返回一個不一樣類型的對象/值。
    • T+ , t* -> t
    • 栗子:List.size( )   : List → int
  • Mutators(變值器):
    • 改變對象屬性的方法 ,
    • 變值器一般返回void,若爲void,則必然意味着它改變了對象的某些內部狀態;固然,也可能返回非空類型 
    • T+ , t* -> t || T || void
    • 栗子:List.add( ) :List x int → List 

 

【考點 ADT的 AF與 RI】

在研究抽象類型的時候,先思考一下兩個值域之間的關係:數據庫

  • 表示域(rep values)裏面包含的是值具體的實現實體。通常狀況下ADT的表示比較簡單,有些時候須要複雜表示。 
  • 抽象域(AF)裏面包含的則是類型設計時支持使用的值。這些值是由表示域「抽象/想象」出來的,也是使用者關注的。

R->A的映射特色:編程

  • 每個抽象值都是由表示值映射而來 ,即滿射:每一個抽象值被映射到一些rep值
  • 一些抽象值是被多個表示值映射而來的,即未必單射:一些抽象值被映射到多個rep值
  • 不是全部的表示值都能映射到抽象域中,即未必雙射:並不是全部的rep值都被映射。

在描述抽象函數和表示不變量的時候,注意要清晰明確:設計模式

  • 對於RI(表示不變量),僅僅寬泛的說什麼區域是合法的並不夠,你還應該說明是什麼使得它合法/不合法。
  • 對於AF(抽象函數)來講,僅僅寬泛的說抽象域表示了什麼並不夠。抽象函數的做用是規定合法的表示值會如何被解釋到抽象域。做爲一個函數,咱們應該清晰的知道從一個輸入到一個輸入是怎麼對應的。

 

【考點:黑盒、白盒框架】

  • 框架(Framework)是整個或部分系統的可重用設計,表現爲一組抽象構件及構件實例間交互的方法;另外一種定義認爲,框架是可被應用開發者定製的應用骨架。前者是從應用方面然後者是從目的方面給出的定義。
  • 爲了增長代碼的複用性,可使用委派和繼承機制。同時,在使用這兩種機制增長代碼複用的過程當中,咱們也相應地在不一樣的類之間增長了關係(委派或繼承關係)。而對於一個項目而言,各個不一樣類之間的依賴關係就能夠看作爲一個框架。一個大規模的項目可能由許多不一樣的框架組合而成。

【白盒框架】數組

  • 白盒框架是基於面向對象的繼承機制。之因此說是白盒框架,是由於在這種框架中,父類的方法對子類而言是可見的。子類能夠經過繼承或重寫父類的方法來實現更具體的方法。
  • 雖然層次結構比較清晰,可是這種方式也有其侷限性,父類中的方法子類必定擁有,要麼繼承,要麼重寫,不可能存在子類中不存在的方法而在父類中存在。
  • 軟件構造課程中有關白盒框架的例子:

 【黑盒框架】併發

  • 黑盒框架時基於委派的組合方式,是不一樣對象之間的組合。之因此是黑盒,是由於不用去管對象中的方法是如何實現的,只需關心對象上擁有的方法。
  • 這種方式較白盒框架更爲靈活,由於能夠在運行時動態地傳入不一樣對象,實現不一樣對象間的動態組合;而繼承機制在靜態編譯時就已經肯定好。
  • 黑盒框架與白盒框架之間能夠相互轉換,具體例子能夠看一下,軟件構造課程中有關黑盒框架的例子,更改上面的白盒框架爲黑盒框架:

【二者對比】app

  • 白盒框架利用subclassing:
    • 容許擴展每個非私有方法
    • 須要理解父類的實現
    • 一次只進行一次擴展
    • 一般被認爲是開發者框架
  • 黑盒框架使用委派中的組合composition:
    • 容許在接口中對public方法擴展
    • 只須要理解接口
    • 一般提供更多的模塊
    • 一般被認爲是終端用戶框架,平臺

 【LSP】

  • 里氏替換原則的主要做用就是規範繼承時子類的一些書寫規則。其主要目的就是保持父類方法不被覆蓋。子類的規約變強!
  • LSP依賴於如下限制:
    • 前置條件變弱或者不變
    • 後置條件變強或者不變
    • 不變量要保持或加強
    • 子類型方法參數:逆變(規約變強,前置變弱 反着變)
    • 子類型方法的返回值:協變(規約變強,前置變強 協同變化)
    • 異常類型:協變
  • 數組是協變的,向上轉型是成立的
Fruit[] apples=new Apple[size];
  •  泛型是類型不變的(泛型不是協變的)。舉例來講 
    • ArrayList<String> 是List<String>的子類型 
    • List<String>不是List<Object>的子類型
  •  類型擦除的結果: <T>被擦除 T變成了Object

【Throwable】

  • 健壯性:輸入錯誤,給出肯定的正常的輸出,傾向於容錯;正確性:出現錯誤報出錯誤,傾向於error。
  • 對外的接口,傾向於健壯性;對內的實現,傾向於正確性。

  • 運行時異常:由程序員處理不當形成,如空指針、數組越界、類型轉換
  • 其餘異常:程序員沒法徹底控制的外在問題所致使的,一般爲IOE異常,即找不到文件路徑等
  • checked異常:
    • checked exception是須要強制catch的異常,你在調用這個方法的時候,你若是不catch這個異常,那麼編譯器就會報錯,好比說咱們讀寫文件的時候會catch IOException,執行數據庫操做會有SQLException等。

  • unchecked異常:
    • 這種異常不是必須須要catch的,你是沒法預料的,好比說你在調用一個 list.szie()的時候,若是這個list爲null,那麼就會報NUllPointerException,而這個異常就是 RuntimeException,也就是UnChecked Exception
    • 常見的unchecked exception:JVM拋出,如空指針、數組越界、數據格式、不合法的參數、不合法的狀態、找不到類等

 

    

【GC的四種策略】                                          

  • 引用計數
    • 基本思想:爲每一個object存儲一個計數RC,當有其餘 reference指向它時,RC++;當其餘reference與其斷開時,RC--;如 果RC==0,則回收它。
    • 優勢:簡單、計算代價分散,「幽靈時間」短 爲0
    • 缺點:不全面(容易漏掉循環引用的對象)、併發支 持較弱、佔用額外內存空間、等
  • Mark-Sweep(標記-清除)算法
    • 基本思想:爲每一個object設定狀態位(live/dead)並記錄,即mark階段;將標記爲dead的對象進行清理,即sweep可階段。
    • 優勢:能夠處理循環調用,指針操做無開銷,對象不變
    • 缺點:複雜度爲O(heap),高 堆的佔用比高時影響性能,容易形成碎片,須要找到root

  • Copying(複製)算法
    • 基本思想:爲了解決Mark-Sweep算法的缺陷,Copying算法就被提了出來。它將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活着的對象複製到另一塊上面,而後再把已使用的內存空間一次清理掉,這樣一來就不容易出現內存碎片的問題。
    • 優點:運行高效、不易產生內存碎片
    • 缺點:複製花費大量的時間,犧牲內存空間

  • Mark-Compact(標記-整理)算法
    • 基本思想:爲了解決Copying算法的缺陷,充分利用內存空間,提出了Mark-Compact算法。該算法標記階段和Mark-Sweep同樣,可是在完成標記以後,它不是直接清理可回收對象,而是將存活對象都向一端移動,而後清理掉端邊界之外的內存。

 

  • 年青一代使用copying算法,年好易貸使用Mark sweep和mark-compact算法

【死鎖】

  • 產生死鎖的四個必要條件:
    • 互斥條件:一個資源每次只能被一個進程使用,即在一段時間內某 資源僅爲一個進程所佔有。此時如有其餘進程請求該資源,則請求進程只能等待。
    • 請求與保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其餘進程佔有,此時請求進程被阻塞,但對本身已得到的資源保持不放。
    • 不可剝奪條件:進程所得到的資源在未使用完畢以前,不能被其餘進程強行奪走,即只能 由得到該資源的進程本身來釋放(只能是主動釋放)。
    • 循環等待條件: 若干進程間造成首尾相接循環等待資源的關係
  • 這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不知足,就不會發生死鎖。
  • 防止死鎖的方法:
    • 加鎖順序:當多個線程須要相同的一些鎖,可是按照不一樣的順序加鎖,死鎖就很容易發生。若是能確保全部的線程都是按照相同的順序得到鎖,那麼死鎖就不會發生。這種方式是一種有效的死鎖預防機制。可是,這種方式須要你事先知道全部可能會用到的鎖,但總有些時候是沒法預知的

    • 使用粗粒度的鎖,用單個鎖來監控多個對象
      • 對整個社交網 絡設置 一個鎖 ,而且對其任何組成部分的全部操做都在該鎖上進行同步。
      • 例如:全部的Wizards都屬於一個Castle,  可以使用 castle 實例的鎖
      • 缺點:性能損失大;
        • 若是用一個鎖保護大量的可變數據,那麼久放棄了同時訪問這些數據的能力;
        • 在最糟糕的狀況下,程序可能基本上是順序執行的,喪失了併發性

 

【用註釋形式撰寫測試策略】

 

【測試覆蓋度】

代碼覆蓋度:已有的測試用例有多大程度覆蓋了被測程序

代碼覆蓋度越低,測試越不充分但要作到很高的代碼覆蓋度,須要更多的測試用例,測試代價高

分類:函數覆蓋 + 語句覆蓋 +分支覆蓋 + 條件覆蓋 + 路徑覆蓋

測試效果:路徑覆蓋>分支覆蓋>語句覆蓋

測試難度:路徑覆蓋>分支覆蓋>語句覆蓋

路徑數量巨大,難以全覆蓋

 

【snapshot】在Runtime,code level,moment

【SOLID】

設計模式前五個原則,偏偏是告訴咱們用抽象構建框架,用實現擴展細節的注意事項而已:

  單一職責原則告訴咱們實現類要職責單一;里氏替換原則告訴咱們不要破壞繼承體系;依賴倒置原則告訴咱們要面向接口編程;接口隔離原則告訴咱們在設計接口的時候要精簡單一;迪米特法則告訴咱們要下降耦合。而開閉原則是總綱(實現效果),它告訴咱們要對擴展開放,對修改關閉。

相關文章
相關標籤/搜索