強轉Integer的危險性以及工具類的理解

今天要記錄的最近上線的一個bug,本身很簡單,修復的也很快但是確實不應該發生。

首先代碼裏是通過redisson從redis裏取出一個關於用戶的緩存,用戶緩存信息使用map結構存儲,因爲value值相對變化比較多,有int型的userid或者string型的username等等,代碼中爲了適應不同類型的value,將map定義爲map<String, Object>,通過Object userId = map.get(“userId”)獲取用戶id,但是在後續使用userId的時候卻偷懶了,想當然的認爲userId這種字段屬於比較“正規”的字段,所以後續代碼中調用其它方法需要傳參userId的時候順手就寫了 (Integer)userId進行強轉,結果上線之後立刻有業務方反應接口返回異常,查log後可以很清晰的看到都是String到Integer的CastException,至於爲什麼userId會是字符串,這種數據本身是否合理那就是內部業務和設計的問題了,這個不過多討論,但是寫代碼的時候確實不應該想當然的直接強轉,畢竟這個操作本身就有風險,尤其是要強轉成類似於Integer這種有格式和範圍要求的類型時,直接選擇信任數據來源不做判斷進行強轉本身就是一種不負責任的代碼。

當時的解決方案是我們系統中有自己的工具類,實現了從String到Integer的轉換,但是差點兒因爲粗心再次出bug,好在組內有經驗的同學提前告知了問題,先看一下我們工具類的代碼:

public static int getInt(Object get) {
    if (get == null) {
        return 0;
    } else {
        String s = get.toString();
        return NumberHelper.isInt(s) ? Integer.parseInt(s) : 0;
    }
}

可以看到如果傳入的字符串爲空,那我們的工具類其實會返回0,但是在我的代碼中null和0完全是兩個不同的概念,所以當返回0之後還需要再次額外處理纔可以,暫且不說工具類這樣設計是否合理,看來以後在使用別人封裝的代碼之前也需要好好閱讀代碼,因爲人和人的想法是不同的,儘量減少這種錯誤的bug數量。

這兩件事給我的經驗總結就是:作爲一名程序員,任何時候都不應該盲目相信別人提供給你的東西,不管是自稱可靠的數據還是一個你剛好需要的封裝方法,一定要記得自己多看看,多判斷一下,這樣才能掌控自己的代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章