天天看點

《資料結構與抽象:Java語言描述(原書第4版)》一2.1.4 讓實作安全

本節書摘來華章計算機《資料結構與抽象:java語言描述(原書第4版)》一書中的第2章 ,第2.1節,[美]弗蘭克m.卡拉諾(frank m. carrano) 蒂莫西m.亨利(timothy m. henry) 著 羅得島大學  新英格蘭理工學院 辛運帏 饒一梅 譯 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

鑒于當今黑客及對重要軟體系統未經授權入侵的現實情況,程式員必須在代碼中添加安全措施,以使程式對使用者是安全的。雖然java為你管理記憶體,檢查數組下标的合法性,且是類型安全的,但一個錯誤會使你的代碼易受攻擊。實作adt時應該時刻銘記安全性,盡管在已有的代碼中增加安全機制可能是困難的。

注:你可以在程式中檢查可能出現的錯誤來練習有安全機制的程式設計(fail-safe programming)。安全可靠程式設計(safe and secure programming)通過驗證輸入給方法的資料和參數的合法性,消除方法的副作用,對客戶和使用者的行為不做任何假設,來擴充有安全機制的程式設計的概念。 安全說明:保護adt實作的完整性 當實作一個adt時,必須問自己的兩個問題是

如果構造方法沒有完全執行,那麼可能會發生什麼?例如,構造方法可能在完成初始化之前就抛出一個異常或錯誤。但是入侵者可能捕獲異常或錯誤,并試圖使用部分初始化的對象。

如果客戶試圖建立一個其容量超出給定範圍的包,那麼可能會發生什麼?

如果這兩個動作可能導緻問題,則我們必須阻止它們。

對于類arraybag,我們想防範前面安全說明中所描述的兩種情形。現在開始細化arraybag的不完整的實作,在類中增加下列兩個資料域,以使代碼更安全:

《資料結構與抽象:Java語言描述(原書第4版)》一2.1.4 讓實作安全

這兩個修改都涉及構造方法。因為預設的構造方法調用帶參數的構造方法,是以僅修改後者就足夠了。為確定客戶不能建立太大的包,構造方法應該檢查客戶所需包的容量與max_capacity值。如果需要的容量太大,則構造方法可以抛出一個異常。

如果所需的容量處在允許範圍内,則arraybag的構造方法為什麼還不能正确完成呢?因為記憶體不足可能導緻配置設定數組失敗。這樣一個事件會導緻錯誤outofmemoryerror。一般地,客戶将這個錯誤看作緻命事件。黑客可能捕獲這個錯誤(就像你捕獲異常一樣),并試圖使用部分初始化的對象。為防止這種情況,類的每個重要方法在執行其操作之前都可以檢查域initialized的狀态。這樣,畸形對象就不會再有動作。對于正确初始化的對象,構造方法将把域initialized置為真。

下面是修改後的構造方法。

《資料結構與抽象:Java語言描述(原書第4版)》一2.1.4 讓實作安全

注意,構造方法在成功完成其他任務後,最後一個動作是将initialized指派為真。還應注意,illegalstateexception是标準運作時異常。

下面來看看如何使用initialized。

在數組bag已成功配置設定的基礎上,arraybag中的任何公有方法在繼續執行之前都應該確定資料域initialized的值為真。如果initialized為假,這樣的方法可以抛出一個異常。例如,可以如下所示修改方法add。

《資料結構與抽象:Java語言描述(原書第4版)》一2.1.4 讓實作安全
《資料結構與抽象:Java語言描述(原書第4版)》一2.1.4 讓實作安全
注:異常securityexception和illegalstateexception都是包java.lang中的标準運作時異常。是以,不需要import語句。

因為我們将在多個方法中檢查initialized,是以為避免代碼重複定義下列私有方法。

《資料結構與抽象:Java語言描述(原書第4版)》一2.1.4 讓實作安全

方法add可以修改為:

《資料結構與抽象:Java語言描述(原書第4版)》一2.1.4 讓實作安全

應該以相同的方式修改核心方法toarray,因為它用到了arraybag的資料域bag。

安全說明:你所熟知的編寫java代碼的某些常見準則,實際上增加了代碼的安全性。這些準則是:

将類的大多數資料域聲明為私有的,如果不是全部。任何公有資料域都應該是靜态和終态的,且有常量值。

避免那些掩蓋代碼安全性的所謂聰明的邏輯。

避免重複代碼。相反,将這樣的代碼封裝為一個可供其他方法調用的私有方法。

當構造方法調用一個方法時,確定這個方法不能被重寫。

安全說明:終态類。注意,我們将arraybag聲明為一個終态類。是以,不會有從arraybag派生的其他類,即arraybag不能是另一個類的父類或基類。終态類比非終态類更安全,因為程式員不能使用繼承來改變它的行為。稍後我們将細化這個方法,定義終态方法而不是整個類。