JAVA陷阱---三元表達式潛藏的坑

當熟悉的三元表達式遇到裝/拆箱發生了未預料到的NPE 如下代碼都是在 jdk 1.8.0_172 版本下運行java

java代碼以下,註釋位置會拋出NPE:優化

public class TestThree {
    public static void main(String[] args) {
        Double a = 1D;
        Double b = 2D;
        Double c = null;

        Double d = false ? a*b : c; // 這裏會拋出NPE
        System.out.println("finished");
    }
}

猜想因爲a*b,Double都進行了拆箱,c由於是null,進行拆箱時就拋出了NPE,爲了驗證,咱們使用javap -c命令看下簡單的字節碼信息code

如上圖所示,第12--21行即c的操做過程,能夠看出第18行Double.doubleValue獲取c的小double值就是拋出NPE的罪魁禍首。blog

可是有個疑問,很明顯能夠看出,通過javac的優化,ab根本不會執行,a、b也都沒有拆箱的操做,爲何要對c進行拆箱呢,直接將null賦值給d不是更簡捷,僅僅由於代碼中使用了ab進行乘法運算就致使了c的拆箱嗎? 咱們來作個驗證:數學

public class TestThree {
    public static void main(String[] args) {
        //Double a = 1D;
        //Double b = 2D;
        Double c = null;

        Double d = false ? null : c; // 這裏不會拋出NPE
        System.out.println("finished");
    }
}

上面的代碼可以成功運行,咱們來看下反編譯出的字節碼內容編譯

能夠看到確實沒有對c的Double.valueOf方法的調用,以前對c的拆箱確實是因爲a*b運算致使的。class

至此,咱們能夠得出一個猜測,在三元表達式中,若是一個結果執行了數學運算,即便表達式的判斷條件短路了此運算,另一個結果也會因爲拆箱而可能致使NPE的發生jdk

最後留一個問題,下面的代碼是否會拋出NPE,其反編譯後的代碼又會是什麼樣子的,想象一下~方法

public class TestThree {
    public static void main(String[] args) {
        Double a = 1D;
        Double b = 2D;
        Double c = null;

        Double d = false ? 1 : c; // 這裏會不會拋出NPE???
        System.out.println("finished");
    }
}
相關文章
相關標籤/搜索