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

Java技術棧發表於2020-08-06

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

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

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 中不會出現 C++ 的沒有編譯提示而導致的邏輯問題,所以 Java 中的 xxx == nullnull == 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 不是任何物件的引用。

總結

好了,今天棧長的分享就到這了,又漲姿勢了吧?

另外,之前這篇《避免空指標的 5 個案例》也不錯的,沒看過的值得閱讀一下。

大家還知道哪些空指標的騷操作?歡迎留言分享哦!~

最後,感謝閱讀,原創不易,各位老鐵們,給個在看、轉發下吧!

推薦去我的部落格閱讀更多:

1.Java JVM、集合、多執行緒、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、後端、架構、阿里巴巴等大廠最新面試題

覺得不錯,別忘了點贊+轉發哦!

相關文章