踩了一個java中三目運算符的坑

        前兩天在開發中遇到了一個很詭異的NPE情況,最後發現是三目運算符的編譯問題,這裏記錄一下。

        簡化後的代碼如下:

Map<String, Long> map = Maps.newHashMap();
map.put("a", 123L);
TmpCls cls = new TmpCls();
cls.setPrice(ObjectUtils.isEmpty(map) ? 0L : map.get("b"));

        原代碼的map其實是從數據庫查出的結果,如果沒查到數據,price就是0,否則就取查到的數據,有時就會出現上面例子的情況,map.get()取不到數據。

        從代碼本身來看,是沒任何問題的,但是遇到這種取不到的情況,就會報一個NPE,百思不得其解。最後看了一下反編譯的結果,才發現其中原因。

        反編譯以後,最後的那個三目運算符的代碼是這樣的

cls.setPrice(ObjectUtils.isEmpty((Object)map) ? 0L : ((long)map.get("b"));

        會發現,它會將map.get()方法外包進行了long型強轉,如果這裏沒有獲取到信息,那麼就是null了。

        具體原因還真不清楚,大概猜想,應該是編譯器根據目標類型進行了推導的結果。

        解決的辦法有三種:

        1、不使用三目運算符,這個比較簡單,就不說明了

        2、對原數據進行判空操作,可以使用Optional進行簡單包裝。

cls.setPrice(ObjectUtils.isEmpty(map) ? 0L : Optional.ofNullable(map.get("b")).orElse(0L));

        3、將後面的邏輯移到外面先做處理,不過這裏也有一個小問題。

long l=ObjectUtils.isEmpty(map) ? 0L : map.get("b");//NPE
Long l=ObjectUtils.isEmpty(map) ? 0L : map.get("b");//正常

        我也是通過這個測試,才推斷應該是編譯器進行了類型推導的。

        另外還需要說一下,我用eclipse和idea都進行了這個測試,發現在eclipse中,第三種解決辦法裏,即使使用包裝類型,也依然會有NPE產生,這個應該是IDE的問題吧,因爲我查了一下用的都是自己安裝的JDK8。

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