Java之三目運算符

 某日,同事給我展示了一塊代碼,問我有沒有什麼問題。(代碼如下 代碼塊1):

int i = 1;
Boolean a = null;
boolean b = false;
System.out.println(i == 1 ? a : b);

集智慧與美貌於一身的我一眼就發現了其中的端倪:當然會報 NPE 了!

但是如果代碼變成這樣的呢(如下 代碼塊2)?

int i = 1;
boolean a = true;
Boolean b = null;
System.out.println(i == 1 ? a : b);

上述代碼塊就是正常的。

爲什麼呢?

這就涉及到了Java中 三目運算符 和 自動裝箱/拆箱 的問題了。

代碼塊1會報錯是因爲條件滿足,取 a 的值。在取 a 的值時,三目運算符中既有基本類型,又有引用類型;JVM會幫我們把引用類型的數據轉換爲基本類型。通過查看 class 文件看到如下代碼(代碼塊3):

int i = 1;
Boolean a = null;
boolean b = false;
System.out.println(i == 1 ? a.booleanValue() : b);

因爲 a 是引用類型,此時調用 a 的方法就會報NPE了。

代碼塊2爲什麼不會報錯呢?

此時三目運算符中的條件滿足,直接就取 a 的值了,因爲 a 是基本類型的,直接就拿來用了,所以程序正常。可以看到 class 文件如下(代碼塊4):

int i = 1;
boolean a = true;
Boolean b = null;
System.out.println(i == 1 ? a : b.booleanValue());

但在實際的業務場景中,我們的代碼不會上上述一樣是 i == 1 的寫法,大部分情況下是動態判斷的。如何避免踩進上述的坑中呢?

其實要解決這個問題也很簡單,就是不讓JVM幫我們拆箱。即把 a 和 b 兩個對象都改爲 Boolean 或 boolean,只要兩個對象統一就好了。

避免採坑的代碼:

int i = 1;
Boolean a = Boolean.TRUE;
Boolean b = Boolean.FALSE;
System.out.println(i == 1 ? a : b);

int i = 1;
boolean a = true;
boolean b = false;
System.out.println(i == 1 ? a : b);

總結:

不止 Boolean/boolean 有這個問題,像 Byte / byte、Integer / int、Short / short、Long / long、Character / char、Float / float、Double / double 都會有這樣的問題。只要代碼規範一點,就不會坑到隊友啦  ╮( ̄▽ ̄)╭

 

最後祝大家碼出好心情,碼出幸福人生!

 

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