前言
最近朋友說遇到一個無解的bug,他有個業務需求是VIP使用者才能參與活動的業務場景。他判斷vip的虛擬碼形如下
private boolean isVip(UserDTO userDTO){
List<Integer> vipUserIds = userService.vipUserIds();
for (Integer vipUserId : vipUserIds) {
if(vipUserId.equals(userDTO.getUserId())){
return true;
}
}
return false;
}
他傳了一個userId為10000(注:10000為示例資料)的vip使用者,結果發現這個判斷一直是false。於是就找到我幫他看下,這程式碼看著沒啥問題,我就讓他先確認一下資料庫是否存在這個vip使用者,朋友非常肯定的說存在的。
排查
因為朋友確定資料庫存在這條記錄,後面我就讓他判斷vip的邏輯上加下日誌,改後的虛擬碼如下
private boolean isVip(UserDTO userDTO){
List<Integer> vipUserIds = userService.vipUserIds();
for (Integer vipUserId : vipUserIds) {
if(vipUserId.equals(userDTO.getUserId())){
return true;
}
}
log.warn("userId-->{} is not in vipList-->{}",userDTO.getUserId(),vipUserIds);
return false;
}
然後日誌神奇的出現
當看到這條日誌,我就有點懵逼了。後面朋友跟我說他懷疑是JDK版本有問題,但我的第六感告訴這不至於。
多年寫bug經驗告訴我,啥都會騙人,只有原始碼不會騙人。因為判斷是否vip的程式碼就一句equal,直接點進去了事。這equal的原始碼如下
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
看到這個程式碼後,我想有些老司機應該有點感覺。後面我就跟朋友說你有沒有可能型別寫錯了,你的userId型別是Integer嗎?於是他翻一下程式碼,果然他userId的型別寫成String
修復
後面朋友把userId的型別也改成Integer,問題圓滿解決。
總結
有時候有些bug難以解決,並不是因為遇到技術難題,而是因為一些我們平時沒注意的小細節引起