天天看點

打破你的認知!Java空指針居然還能這樣玩,90%人不知道…

相信在座的各位都遇到過空指針異常,不甚其煩,本文不是教你避免空指針,而是一些對空指針其他方面的了解。

本文可能有點另類,也可能會打破你對空指針的認知。

1、null.method() 空指針?

我們知道調用一個對象的方法,如果對象為 null 肯定會報空指針錯誤的,但你确定一定會嗎?

不一定!

來看下面的示例:

/**
 * 通路靜态方法
 * @from 微信公衆号:Java技術棧
 */
private static void test() {
    NullTest nullTest = null;

    // hello
    nullTest.test1("hello");
}

/**
 * @from 微信公衆号:Java技術棧
 * 關注擷取更多好玩的 Java 技術幹貨
 */
private static void test1(String text) {
    System.out.println(text);
}      

如果

null

對象指向該類型的靜态方法,不但不會報空指針錯誤,而且還會運作正常,是不是很6?

因為靜态方法不屬于任何對象,它屬于類本身的,相當于直接調用類的靜态方法。

2、拆箱空指針

是的,大家要注意拆箱引發的空指針風險,不知道的趕緊往下看,來看下面的例子:

/**
 * 拆箱
 * @from 微信公衆号:Java技術棧
 */
private static void test() {
    Integer i = null;

    // //NullPointerException
    int ii = i;

    System.out.println(ii);
}      

拆箱如果為 null 時,引發空指針錯誤。

這個在最新的《阿裡巴巴開發手冊》中也提到了,連結裡面舉了三目運算符拆箱時的空指針問題,沒看過的可以點進去看,這裡就不具體展開了。擷取這份最新開發手冊,請在公衆号Java技術棧回複手冊。

3、運算符空指針

大家要注意了,運算符使用不當也會引發空指針異常,來看下面的例子:

/**
 * 運算符
 * @from 微信公衆号:Java技術棧
 */
private static void test5() {
    Integer i = null;
    Integer j = null;

    // true
    System.out.println(i == j);

    // false
    System.out.println(i != j);

    // NullPointerException
    System.out.println(i > j);

    // NullPointerException
    System.out.println(i < j);

    //NullPointerException
    System.out.println(i & j);
}      

例子很明顯吧,使用 ==、!= 運算符比較是否相等不會有問題,但使用 > < & 等需要計算的運算符就會引起空指針異常。

4、xxx == null引發空指針?

經常看部落格或者身邊的同僚說,字元串比較,常量要放前面,為了避免空指針風險,這個對于 equals 來說确實要這樣寫。

但是,居然還有人說,甚至也有很多人也是這麼在寫, == 比較,null 也要放前面,這也是為了避免空指針?還是為了避免啥風險?

首先要搞清楚為什麼有 null == xxx 這個寫法?

這個寫法的初衷是 C++ 為了避免邏輯錯誤的,因為 C++ 寫 if(xxx = NULL) 是不會報編譯錯誤的(變量指派,永遠為真),而寫 if(NULL = xxx) 是會有編譯錯誤的。

是以在 C++ 建議把 NULL 放在前面,是為了避免程式員把 == 寫成 = 引起的邏輯錯誤的。

而在 Java 裡面,if(xxx = null) 是有編譯錯誤提示的:

打破你的認知!Java空指針居然還能這樣玩,90%人不知道…

是以 Java 中不會出現 C++ 的沒有編譯提示而導緻的邏輯問題,是以 Java 中的 xxx == null 和 null == xxx 是等價的,null 放前面也是沒有任何意義的。

我們甚至還可以在 Java 中寫 null == null 的判斷,這也是 OK 的,完全沒問題的。

下面是完整的示例:

/**
 * 運算符
 * @from 微信公衆号:Java技術棧
 */
private static void test() {
    Integer i = null;

    // i is null
    if (null == i){
        System.out.println("i is null");
    }

    // i is null
    if (i == null){
        System.out.println("i is null");
    }

    // i == j
    Integer j = null;
    if (i == j){
        System.out.println("i == j");
    }

    // 編譯錯誤
    if (i = null){
        System.out.println("i is null");
    }
}      

有沒有小夥伴也被這個說法迷糊過?

5、null instanceof 空指針?

null instanceof 會發生空指針異常麼?

不會!

/**
 * instanceof
 * @from 微信公衆号:Java技術棧
 */
private static void test() {
    Integer i = null;

    // false
    if(i instanceof Number){
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // false
    if(null instanceof Number){
        System.out.println("true");
    } else {
        System.out.println("false");
    }
}      

如果為 null, instanceof 右邊可以是任意引用類型,但結果始終輸出 false,因為 null 不是任何對象的引用。