Java 三目運(yùn)算符(conditional operator?:)

參考

問題

下面這段代碼竟然報(bào)了NullPointerException異常.

public static void main(String[] args) {
      Map<String, Boolean> map = new HashMap<>();
       // Exception in thread "main" java.lang.NullPointerException
       boolean b = (map!=null ? map.get("test") : false);
   }

問題來源是Java的Autoboxing和Boxing機(jī)制.

三目運(yùn)算符求值順序

首先是右結(jié)合的.

The conditional operator is syntactically right-associative (it groups right-to-left). Thus, a?b:c?d:e?f:g means the same as a?b:(c?d:(e?f:g)).

其次再關(guān)注整體的返回值類型是什么, 首先 ? Expression1 : Expression2中的兩個(gè)表達(dá)式, 要么是同一個(gè)類型, 要么是能夠相互轉(zhuǎn)換的, 但是最后會(huì)統(tǒng)一為一個(gè)類型, 規(guī)則(下面只摘錄了一部分, 完整的可以去三目運(yùn)算符的官方文檔查看)如下:

  1. If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.

  2. If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

  3. If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.

對(duì)于上面的boolean b = (map!=null ? map.get("test") : false);:

  • map.get("test") 的返回值是Boolean
  • false 是原始類型boolean

根據(jù)規(guī)則2, boolean是原始類型, 而Boolean類型是boolean裝箱后的結(jié)果, 即Boolean. 所以最終的返回值類型為boolean.
然后開始對(duì)整體求值, 首先map != null肯定是成立的, 所以會(huì)對(duì)map.get("test")求值, 因?yàn)閙ap中不存在test這個(gè)key, 所以get方法返回了null, 這也是整體的返回值. 因?yàn)?code>map.get()返回值類型是Boolean, 而因?yàn)橐?guī)則2, 所以會(huì)將map.get()對(duì)的返回值進(jìn)行拆箱操作, 即調(diào)用Boolean.booleanValue()方法, 而此時(shí)map.get()的返回值是一個(gè)null, 所以出現(xiàn)了NullPointerException.

經(jīng)過進(jìn)一步測(cè)試, 有以下結(jié)果:
根據(jù)B那句賦值語句來看, 應(yīng)該是編譯器判斷又要從boolean轉(zhuǎn)換回Boolean所以map.get()的結(jié)果應(yīng)該不會(huì)再拆箱了.

        Map<String, Boolean> map = new HashMap<>();
        // Exception in thread "main" java.lang.NullPointerException
//        boolean b = (map!=null ? map.get("test") : false);

        // 沒有異常
//        Boolean B = (map!=null ? map.get("test") : false);

        // Exception in thread "main" java.lang.NullPointerException
//        if ((map!=null ? map.get("test") : false)){
//            ;
//        }

        // Exception in thread "main" java.lang.NullPointerException
//        boolean b1 = (map!=null ? map.get("test") : Boolean.FALSE);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容