Java編程中空指針(NullPointerException)的防範經驗分享

在寫代碼的過程當中,出現最多的異常可能就是空指針異常了。說白了,空指針異常就是你拿一個不存在的對象,去訪問它的成員屬性或者方法。咱們暫且看下面的代碼:java

public static String getString() {
    return null;
}

public static void main(String[] args) {
    // 此處返回null
    String str = getString();
    System.err.println(str.length());
}
複製代碼

很明顯,上面程序運行的結果確定是排除煩人的java.lang.NullPointerException:web

Exception in thread "main" java.lang.NullPointerException
	at org.springframework.web.SpringServletContainerInitializer.main(SpringServletContainerInitializer.java:187)
複製代碼

可是,其實空指針自己並非那麼可怕,可怕的是命名咱們知道有這麼一種可能會出現空指針異常,可是咱們殊不知道或者無法提早預判,就像上面的代碼片斷,在eclipse IDE中是沒有任何提示的,以下圖:spring

那麼有什麼辦法咱們能夠提早預判到可能會拋出NullPointerException的代碼塊,而後作防空處理呢!答案是確定的。下面我將介紹幾種常見的防空方式,注意,這不是演習,這不是演習,這不是演習。哈哈!bash

  • 一、使用註解方式標識參數、方法返回值是否爲空
  • 二、使用Java8提供的Optional類聲明咱們的API

下面我將一一舉例進行探討(IDE以eclipse爲例):eclipse

前置處理:ui

首先咱們要在eclipse啓用基於註解的檢查,在Windows->Preference->Java->Compiler->Errors/Warnings->Null Analysis,以下圖所示:編碼

1、使用註解方式標識參數、方法返回值是否爲空

JSR 303/305和Spring都提供了相應的的註解,以下所示:spa

  • 一、JSR 303/305:@Nonnull@Nullable
  • 二、Spring:@NonNull@Nullable

在eclipse啓動空檢驗以後,要想使上面的@Nullable註解生效,還須要將註解的全路徑類型配置到上圖的Use default annotations for null sercifications,配置以下圖:3d

配置完成以後,再看下面代碼:指針

/**
 * 表示返回的值可能爲空
 * @return
 */
@Nullable
public static String getString() {
    return null;
}

/**
 * 參數不能爲空
 * @param str
 * @return
 */
public static String getName(@NonNull String str) {
    return null;
}

public static void main(String[] args) {
    // 此處返回null
    String str = getString();
    System.err.println(str.length());
    
    // 參數爲空
    getName(null);
}
複製代碼

這樣子可能爲空的代碼就一目瞭然了。固然了,其中的原理仍是IDE支持掃描JSR規範的相關注解,Spring的@NonNull@Nullable也是基於JSR註解實現的,可用於聲明方法,字段或者參數。

2、Optional

Java8提供了對null進行建模的類,它叫Optional。咱們能夠把它理解爲一個容器,容器裏保存的,能夠是方法的放回值,也能夠是方法參數值,若是方法返回值爲null或者參數值爲null,那麼就返回一個空容器對象。請看下面代碼:

/**
 * 表示返回的值可能爲空
 * @return
 */
public static Optional<String> getString() {
    // 返回空容器,裏邊什麼也沒有
    return Optional.empty();
}

/**
 * 參數不能爲空
 * @param str
 * @return
 */
public static String getName(Optional<String> str) {
    return str.get();
}

public static void main(String[] args) {
    // 此處返回Optional.empty()
    Optional<String> optional = getString();
    // 若是返回的是空容器,那麼就返回orElse的值,不然,返回容器裏的值
    String value = optional.orElse("otherValue");
    // 輸出otherValue
    System.err.println(value);
    
    // 參數爲空
    getName(Optional.of("value"));
}
複製代碼

使用Optional類很方便對可能返回null的值進行建模,同時Optional裏邊提供了不少有用的方法容許咱們傳入一個lambda表達式進行處理,很是方便。

總結

  • 一、若是隻是單純想處理代碼邏輯中可能出現的null異常,那麼其實我以爲使用IDE結合註解的方式可能會更加方便一點,固然使用Optional也是能夠的
  • 二、若是咱們想提供一個對外的API,我認爲將API的成員屬性、方法返回值聲明爲Optional可能會更好一點,由於別人一看就知道,該API方法簽名可能會返回空值,使用者只須要用一個Optional對接收便可!
  • 三、要想減小空異常,關鍵還得提高本身的編碼能力!身正不怕影子斜。
相關文章
相關標籤/搜索