不要只替換乙個類

2021-07-05 23:04:28 字數 1384 閱讀 6835

我們經常在系統中定義乙個常量介面(或常量類),以囊括系統中所涉及的常量,從而簡化**,方便開發,在很多的開源專案中已採用了類似的方法,比如在struts2中,org.apache.struts2.strutsconstants就是乙個常量類,它定義了struts框架中與配置有關的常量,而org.apache.struts2.strutsstatics則是乙個常量介面,其中定義了ognl訪問的關鍵字。

關於常量介面(類)我們來看乙個例子,首先定義乙個常量類:

public class constant  

這是乙個非常簡單的常量類,定義了人類的最大年齡,我們引用這個常量,**如下:
public class client   

}

執行的結果非常簡單(結果省略)。目前的**編寫都是在「智慧型」ide工具中完成的,下面我們暫時回溯到原始時代,也就是回歸到用記事本編寫**的年代,然後看看會發生什麼奇妙事情(為什麼要如此,稍後會給出答案)。

修改常量constant類,人類的壽命增加了,最大能活到180歲,**如下:

public class constant  

輸出的結果是:「人類壽命極限是:150」,竟然沒有改變為180,太奇怪了,這是為何?

原因是:對於final修飾的基本型別和string型別,編譯器會認為它是穩定態(immutable status),所以在編譯時就直接把值編譯到位元組碼中了,避免了在執行期引用(run-time reference),以提高**的執行效率。針對我們的例子來說,client類在編譯時,位元組碼中就寫上了「150」這個常量,而不是乙個位址引用,因此無論你後續怎麼修改常量類,只要不重新編譯client類,輸出還是照舊。

而對於final修飾的類(即非基本型別),編譯器認為它是不穩定態(mutable status),在編譯時建立的則是引用關係(該型別也叫做soft final),如果client類引入的常量是乙個類或例項,即使不重新編譯也會輸出最新值。

千萬不可小看了這點知識,細坑也能絆倒大象,比如在乙個web專案中,開發人員修改乙個final型別的值(基本型別),考慮到重新發布風險較大,或者是時間較長,或者是審批流程過於繁瑣,反正是為了偷懶,於是直接採用替換class類檔案的方式發布。替換完畢後應用伺服器自動重啟,然後簡單測試一下(比如本類引用final型別的常量),一切ok。可執行幾天後發現業務資料對不上,有的類(引用關係的類)使用了舊值,有的類(繼承關係的類)使用的是新值,而且毫無頭緒,讓人一籌莫展,其實問題的根源就在於此。

恩,還有個小問題沒有說明,我們的例子為什麼不在ide工具(比如eclipse)中執行呢?那是因為在ide中不能重現該問題,若修改了constant類,ide工具會自動編譯所有的引用類,「智慧型」化遮蔽了該問題,但潛在的風險其實仍然存在。

注意 發布應用系統時禁止使用類檔案替換方式,整體war包發布才是萬全之策。

乙個類如何只建立乙個物件?

思路 由於只有全域性與靜態可以被類中所有成員使用,而類中存在靜態的成員變數 成員函式,由此考慮用靜態來解決。具體方法 建構函式只呼叫一次 將成員函式 構造 析構 定義為私有,定義靜態成員變數char s 所有變數所共有 再編寫 靜態 2個函式 建立與釋放函式 函式1功能 當s null new開闢空...

關於Regex Replace只替換第乙個的問題

都知道正規表示式吧,老牛x老牛x的東西了,就是如果你長時間不用,可能很難入門,我也是,當時看的時候都明白了,用的時候也只是那麼一兩回,幾天不用,全忘光了,今天又遇到乙個這樣的問題,乙個關於regex.replace只替換第乙個的問題,記得在js裡用replace的時候就是只替換第乙個匹配的,沒辦法只...

iOS正規表示式替換乙個或乙個以上空格

碰到乙個問題,要將乙個字串中的空格替換成 乙個以上的 要減少到乙個,比如 替換前 你 好 嗎?替換後你 好 嗎?這裡需要兩步,先將空格替換成 再將多個 合併為乙個。第一步很好解決 nsstring str 你 好 嗎?str str stringbyreplacingoccurrencesofstr...