這其實是我遇到的乙個線上bug,在這裡分享給大家。
如果是用反射,那就很簡單了,畢竟泛型只是在編譯期進行約束,對執行期是無能為力的。
想想看,如果不使用反射,有沒有辦法做到呢?
/**
* 主要業務邏輯
*/public static void main(string args) else
}/**
* 這是公司提供的乙個公共工具方法,獲取集合中,每個物件的某個欄位的值的集合
** @param list 資料物件集合
* @param key 字段
* @return 值的集合
*/public static listtolist(listlist, string key)
其中的databo
物件簡化如下:
public class databo
public void set(string key, object value)
@override
public string tostring() ';}}
原本我這裡的業務需求是,取列表資料中,所有「a」欄位的值出來,判斷其中是否含有1。
已知資料庫裡「a」字段定義為int型別,並且確認了有一條資料在「a」欄位上存的是1。但是**上線一跑,出bug了。
查出來怎麼就走到「不包含1」的分支裡去了呢?也沒有報錯,難道底層服務的getlist()方法有什麼特殊處理,把資料庫a=1的那條資料給過濾掉了嗎?
於是我加了點日誌,把list
和intergerlist
的元素列印出來,看看裡面到底存了什麼東西。於是又上線一版,觀察一看,神奇的事情出現了,裡面明明有1啊??!為啥會走到下面「不包含1」的分支呢?見鬼了!
於是我只能本地debug了一下,才發現資料庫查到的集合裡,「a」字段返回的是個字串"1"!而arraylist的contains()方法,底層是用equals()去比較是否存在的。"1".equals(1),結果肯定是false,所以認為不存在。
好吧,雖然資料庫的「a」字段定義為int型別,但是底層服務估計**有bug,把integer型別的字段,轉換成了string型別返回給上層服務了。
但轉念一向,不對啊,我明明定義的是list
型別的變數,如果是這樣的話,就算查出來"a"字段不是個integer型別的值,那tolist()方法也應該是拋個j**a.lang.classcastexception
才對,怎麼可能正常往下走呢?list
變數指向的物件裡,為什麼會存進去乙個字串呢?為什麼tolist()方法的.map(x -> (t)x.get(key))
這一行沒有報錯呢?
問題很明顯就是出在了tolist()方法裡,那個強制型別轉換並沒有生效。開頭我們說了,j**a的泛型,只是在編譯期進行約束,對執行期是無能為力的。那麼我們首先就應該想到的就是j**a的泛型擦除機制,我們對demo類進行編譯、再反編譯看看。
反編譯可以發現,原來tolist()方法中,強制型別轉換被擦除了。所以返回的其實並不是list
物件,而是list物件,沒有泛型限制。很明顯是這個方法有bug,其實就是泛型方法使用錯誤了。
本來這個線上bug到這裡就已經搞清楚了,如果只是要快速修復上線也很容易就能解決,把tolist()方法返回的集合改成list
,然後判斷集合是否包含字串"1"就行。
但我們想,如果後面又有別的同事遇到這個問題了怎麼辦呢,也會一臉懵逼,最好還是希望tolist()方法丟擲個j**a.lang.classcastexception
,而且還要做到原來這個方法的效果,該怎麼修改這個方法呢?
我們可以增加乙個引數,告訴方法你希望返回乙個什麼型別的值:
這樣的話,如果tolist()方法還是返回原來的list
,就會拋異常:
而且如果前後限制的型別不一致,編譯期也會報錯,泛型就起作用了:
到此這個問題徹底解決。
/**
* 查資料庫,獲取資料物件的集合
** @return 資料物件的集合
*/public static listgetlist()
ThreadLocal存List遇到的坑
之前為了方便乙個service下共用list,將list作為類成員變數,當然有點執行緒安全意識的兄弟們都知道不能就這麼直接加在上面。1 public class permservice 當然用鎖 synchronized 又還不至於,於是這裡用了執行緒本地變數threadlocal,如下 1 pub...
三十公里有可能 !遠距離無線網橋
三十公里有可能 遠距離無線網橋 無線網路一般有什麼弱點?您會說,訊號不夠好,距離不夠長是硬傷。是麼?那今天編者就為你介紹一款沒有這兩種硬傷的產品 紅線an 30i 支援點對點 ptp 和點對多點 ptmp 的網路結構。同時提供兩種介面 ip和e1 基於ip 平台的傳輸,在裝置內部入ip轉 e1的模組...
list 裡可以放陣列嗎?
昨天看到乙個演算法題目,他的示例給的是 1 10 1 3 5 7 9 11 13 15 17 19 0 51 5 7 11 18 1 0 這樣,第乙個數字表示有3組資料。每兩行一組,上面一行的第二個數字表示下面一行的數字個數。但是這個題目沒有像樂扣那樣,給出方法名和方法引數。我就不知道該怎麼寫了。第...