不是吧,還有人不知道三目運(yùn)算符的BUG
前言
文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/bin392328206/six-finger
種一棵樹最好的時(shí)間是十年前,其次是現(xiàn)在
我知道很多人不玩qq了,但是懷舊一下,歡迎加入六脈神劍Java菜鳥學(xué)習(xí)群,群聊號碼:549684836 鼓勵(lì)大家在技術(shù)的路上寫博客
周末快樂,送大家一句話
這世上每個(gè)人都背負(fù)著枷鎖,有的人是別人給的,有的是自己給的。
絮叨
三目運(yùn)算符一直是眾多開發(fā)者信手拈來的一種寫法,它簡化了if-else的臃腫的寫法,而是用一行代碼替代,就感覺無形之中秀了一把。
殊不知,這么帥氣的代碼也暗藏著一個(gè)BUG。
緣由
頭天晚上發(fā)布了一個(gè)功能,本以為是波瀾不驚的一個(gè)需求,結(jié)果第二天kibana打出了成噸的NPE日志。這些NPE日志大多都不約而同都指向了我寫的一行代碼,我立馬推了下我的眼鏡,開始排查起來了。
問題代碼
Kibana的堆棧日志定位在第899行。
resultMap.put("unAuditPurchaseOrder", switchConf == null ? 0 : switchConf.getUnAuditPurchaseOrder());
1.檢查了resultMap,它在上面有實(shí)例化,不可能為空。2.檢查switchConf,但是在這里有判空,也不會報(bào)錯(cuò)。那是怎么回事????
繼續(xù)排查
既然肉眼看不出,那么只能找一臺測試機(jī),用一下Arthas看一下具體的情況。(線上慎用,因?yàn)榭赡軙斐煽D)
trace com.raycloud.dmj.tj.services.customer.CustomerButtonService getPurchaseConfig -n 5 '1==1' --skipJDKMethod false

果然,這里就發(fā)現(xiàn)了端倪。這里竟然執(zhí)行了intValue()!也就是說如果switchConf.getUnAuditPurchaseOrder()這個(gè)是null,那么就很明顯發(fā)生了NPE。
看一下字節(jié)碼
為了顯現(xiàn)效果,我換一個(gè)簡單的程序
public class Test {
public static void main(String[] args) {
Integer i = null;
System.out.println(1 != 1 ? 0 : i);
}
}
定位到class文件目錄,執(zhí)行
javap -c -l Test

然后我又改了一下程序
public class Test {
public static void main(String[] args) {
Integer i = null;
System.out.println(1 == 1 ? 0 : i);
}
}
這次運(yùn)行并不會報(bào)錯(cuò),看一下它的JVM指令:

因?yàn)槿窟\(yùn)算符的結(jié)果是前者的邏輯,即返回一個(gè)常量0。
解釋
由上面的實(shí)驗(yàn)可以發(fā)現(xiàn),JVM在解釋三目運(yùn)算符的時(shí)候,會對兩個(gè)邏輯語句進(jìn)行數(shù)據(jù)類型校驗(yàn),按照前者的數(shù)據(jù)類型為準(zhǔn)。實(shí)驗(yàn)中,數(shù)據(jù)類型是基本數(shù)據(jù)類型,所以,如果邏輯走到了后者,那么就會進(jìn)行自動(dòng)的拆箱。這個(gè)隱式的操作就是造成這個(gè)BUG的原因。

解決
既然知道原因了,那么只要統(tǒng)一數(shù)據(jù)類型就行:
public class Test {
public static void main(String[] args) {
Integer i = null;
System.out.println(1 != 1 ? new Integer(0) : i);
}
}
然后按照慣例,我們還是看一下他的JVM指令:

拾遺
后來在無意之中發(fā)現(xiàn),原來這個(gè)例子在《阿里巴巴開發(fā)手冊》當(dāng)中也有被記錄

其實(shí)說的也是一回事情!
結(jié)尾
文章出自掘金 浮沉_fuchen
日常求贊
好了各位,以上就是這篇文章的全部內(nèi)容了,能看到這里的人呀,都是真粉。
創(chuàng)作不易,各位的支持和認(rèn)可,就是我創(chuàng)作的最大動(dòng)力,我們下篇文章見
六脈神劍 | 文 如果本篇博客有任何錯(cuò)誤,請批評指教,不勝感激 !
