當前位置: 妍妍網 > 碼農

程式碼優雅之道——Java如何判空

2024-02-18碼農

來源:juejin.cn/post/7224027867084292154

  • 1 前言

  • 2 List的判空

  • 3 String的判空

  • 4 Optional

  • 4.1 Optional物件的建立

  • 4.2 使用場景

  • 5 總結

  • 1 前言

    實際計畫中我們會有很多地方需要判空校驗,如果不做判空校驗則可能產生 NullPointerException 異常。

    針對異常的處理我們在上一篇有提及:

    先來看一下實際計畫中一些判空方式

    通常我們判斷一個物件是否為Null,可以使用 java.util 中的 Objects.nonNull(obj) 、hutool中的ObjectUtil或者直接 null != obj

    2 List的判空

    像List這種比較特殊的在計畫中可能不僅僅是判斷非空了。對於List來說不等於null和 List.size() 不等於0是兩回事,公司也有實習生常常有把這兩個混淆的情況,list不等於null說明已經初始化了,堆記憶體中有一塊屬於它的地盤,而size為0說明還沒往裏面放東西,舉個例子說就是不等於null代表我現在有個瓶子,size大於0說明我向瓶子裏裝水了。

    實際計畫中也發現有直接用 list.isEmpty() 去判斷的,來看一下源碼:

    相當於判斷瓶子裏有沒有水(前提是瓶子已經存在,若瓶子不存在,則會丟擲 NullPointerException 異常)。

    所以通常情況下會連用 list != null && list.size > 0 來判斷,或者直接使用HuTool中CollUtil工具的isEmpty。諸如此類的還有Set、Map等

    3 String的判空

    這裏還是用瓶子與水的概念,String為null時呼叫 equals(String) length() 等操作丟擲 java.lang.NullPointerException

    針對字串判空有以下幾種方式:

    1、大多數人使用的方法之一,直觀,方便,但效率低下:

    if(a == null || a.equals(""));

    2、比較字串長度,高效:

    if(a == null || a.length() == 0);

    3、Java SE 6.0 才剛剛開始提供,效率和方法二差不多:

    if(a == null || a.isEmpty());

    當然還可以使用 org.apache.commons.lang.StringUtils 工具。

    StringUtils.isNotBlank(a);

  • StringUtils.isNotBlank(null) = false

  • StringUtils.isNotBlank("") = false

  • StringUtils.isNotBlank(" ") = false

  • StringUtils.isNotBlank("bob") = true

  • StringUtils.isNotBlank(" bob ") = true

  • 該工具類中還有個 isNotEmpty() 方法,從註釋可以很明顯看出二者的差別

    StringUtils.isNotEmpty(a);

  • StringUtils.isNotEmpty(null) = false

  • StringUtils.isNotEmpty("") = false

  • StringUtils.isNotEmpty(" ") = true

  • StringUtils.isNotEmpty("bob") = true

  • StringUtils.isNotEmpty(" bob ") = true

  • 4 Optional

    Optional的出現就是用來防止 NullpointException 的。常見的方法有:

  • .empty() 建立一個空的Optional例項

  • .of(T t) : 建立一個Optional 例項,為null時報異常

  • .ofNullable(T t) : 若t 不為null,建立Optional 例項,否則建立空例項

  • isPresent() : 判斷容器中是否有值

  • ifPresent(Consume lambda) 容器若不為空則執行括弧中的Lambda運算式

  • orElse(T t) : 獲取容器中的元素,若容器為空則返回括弧中的預設值

  • orElseGet(Supplier s) : 如果呼叫物件包含值,返回該值,否則返回s 獲取的值

  • orElseThrow() : 如果為空,就丟擲定義的異常,如果不為空返回當前物件

  • map(Function f) : 如果有值對其處理,並返回處理後的Optional,否則返回 Optional.empty()

  • flatMap(Function mapper) : 與map 類似,要求返回值必須是Optional

  • T get() 獲取容器中的元素,若容器為空則丟擲 NoSuchElement 異常

  • 先看個常見的範例:

    baseInfo類中有布爾型別的內容,是空返回false,不為空取其值,需要四行。

    當使用Optional時,一行搞定,非常的優雅。

    4.1 Optional物件的建立

    public final class Optional<T> {
    private static final Optional<?> EMPTY = new Optional<>();
    private final T value;
    //可以看到兩個構造方格都是private 私有的
    //說明 沒辦法在外面new出來Optional物件
    private Optional() {
    this.value = null;
    }
    private Optional(T value) {
    this.value = Objects.requireNonNull(value);
    }
    //這個靜態方法大致 是建立出一個包裝值為空的一個物件因為沒有任何參數賦值
    public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
    }
    //這個靜態方法大致 是建立出一個包裝值非空的一個物件 因為做了賦值
    public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
    }
    //這個靜態方法大致是 如果參數value為空,則建立空物件,如果不為空,則建立有參物件
    public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
    }
    }

    4.2 使用場景

    場景1:在service層中 查詢一個物件,返回之後判斷是否為空並做處理

    場景2:使用Optional 和函數語言程式設計,一行搞定

    5 總結

    每種方法的存在必然有適用的場景,有些情況下這種鏈式編程,雖然程式碼優雅了。但是,邏輯性沒那麽明顯,可讀性有所降低,大家計畫中看情況酌情使用。

    >>

    END

    精品資料,超贊福利,免費領

    微信掃碼/長按辨識 添加【技術交流群

    群內每天分享精品學習資料

    最近開發整理了一個用於速刷面試題的小程式;其中收錄了上千道常見面試題及答案(包含基礎並行JVMMySQLRedisSpringSpringMVCSpringBootSpringCloud訊息佇列等多個型別),歡迎您的使用。

    👇👇

    👇點選"閱讀原文",獲取更多資料(持續更新中