13161216443

您所在位置: 首頁> 學習課程> java培訓班 | Java 是如何優雅地處理NPE問題?

java培訓班 | Java 是如何優雅地處理NPE問題?

發布百知教育 來源:學習課程 2019-12-03

1. 前言

對于 Java 開發者來說,null 是一個令人頭疼的類型,一不小心就會發生 NPE (空指針) 問題。也是 Java 語言為人詬病的一個重要原因之一。在我們消除可惡的 NPE 問題之前我們要回顧一下 Java 中 null 的概念。

2. Java 中的 null

翻譯自 Oracle Java 文檔[1]

Java 語言中有兩種類型,一種是 基本類型 ,另一種是 引用類型。還有一種沒有名字的特殊類型,即表達式 null 。由于 null 類型沒有名稱,所以不可能聲明為 null 類型的變量或者轉換為 null 類型。null 引用是null 類型表達式唯一可能的值。null 引用可以轉換為任意引用類型。事實上,程序員可以忽略null類型,可以認為null僅僅是一個可以成為任何引用類型的特殊符號。

從上面的描述我們可以了解到,其實 null 僅僅是一個關鍵字標識量,既不是一種類型也不算對象,無法直接聲明 null 和被轉換為 null,僅僅只能被引用,null 可以轉換為任何引用類型。當一個 Java 引用類型對象被引用為 null 時代表當前對象不引用對象,并沒有為其分配內存。這也是我們在沒有引用的對象上調用方法出現空指針的根本原因。大多數情況下 Java 開發者使用 null 是為了表示某種不存在的意思。

3. NPE 問題的解決

很多時候我們對數據是否存在有自己的期望,但是這種期望并不能直接被我們掌控,一個返回值為 null 所表達的意思并不明確過于模糊,往往通過是否判斷為 null 來規避空指針問題。于是 Google 工程師在他們的 Guava 工具類庫中設計了 Optional<T> 來解決 null 不可控的問題。讓你在不得不使用 null 的時候,可以更加簡便明確的使用 null 并幫助你避免直接使用 null 帶來的問題。Java 8 將此設計吸收。我們可以直接使用 Java 提供的 Optional來解決空指針問題。接下來我們來研究一下 Java 8 中的 Optional 。

4. Java 8 中的 Optional

Java 8 中的 Optional 是一個可選值的包裝類。它的意義不僅僅幫我們簡化了 NPE 問題的處理,同時也是 Java 函數式編程的一個重要輔助。我們接下來將對其 API 進行講解以幫助你在實際開發中使用他們。

4.1 Optional 聲明

Optional 只能通過靜態方法來聲明。它提供了三個靜態方法:

empty() 返回一個值為 null  Optional 實例

  Optional<Object> empty = Optional.empty();

of(T) 返回一個值不為 null  Optional 實例

 Optional<String> nonNull = Optional.of("Felordcn");

ofNullable() 返回一個值可能為 null  Optional 實例

 // value 值來自其它不確定的來源
String value = SomeApi.source();
// 可能為 null
Optional<String> nullable = Optional.ofNullable(value);
// 也可能不為 null
Optional<String>  hasValue = Optional.ofNullable(value);

4.2 其它方法

isPresent() 如果值存在則返回 true,否則返回 false 。如果 Optional 值不確定,可使用該方法進行安全校驗

 Optional<String> nonNull = Optional.of("Felordcn");
 // true
 boolean present =nonNull.isPresent();

get() 獲取 Optional 中的值,如果為空會拋出 NoSuchElementException 異常

 Optional<String> nonNull = Optional.of("Felordcn");
 // Felordcn
 String str = nonNull.get();

ifPresent(Consumer) 如果值存在則該值被消費函數 Consumer 消費 , 否則不做任何事情。isPresent() 加強版


     //  非空打印出字符串
     nullable.ifPresent(System.out::println);

    //等同于
     if (nullable.isPresent()) {
                System.out.println(nonNull);
     }

filter(Predicate) 如果值滿足斷言函數 Predicate 則返回該 Optional,否則返回 Optional.empty()

 Optional<String> nonNull = Optional.of("Felordcn");
Optional<String> felord = nonNull.filter(s -> s.startsWith("Felord"));
// str = "Felordcn"
String str = felord.get();

map(Function) 獲取元素某個屬性的 Optional 。如果該屬性為 null 返回 Optional.empty() ,否則返回對應值的 Optional

 Optional<User> userOpt = Optional.ofNullable(user);
//  username 為空 則為 空  Optional
Optional<String> usernameOpt = userOpt.map(User::getUsername);

flatMap(Function) 有時候我們會返回 Optional<Optional<T>> 非常不便于處理,我們需要將元素展開,可使用該方法處理,參考 Stream Api 中的相關方法

orElse(other) 如果 Optional 的值存在,返回 Optional, 否則指定一個 Optional

orElseGet(Supplier) 如果 Optional 的值存在,返回 Optional, 否則指定一個執行 Supplier 函數來獲取值

orElseThrow(Supplier<? extends Throwable>) 如果 Optional 的值存在,返回 Optional, 否則拋出一個指定 Supplier 函數提供的異常

4.3 Java 9 中的新 API

or(Supplier) orElseGet 的改進類型。不單單返回具體的值,而可以函數式的返回 Optional

stream()  Optional  Stream 打通

ifPresentOrElse(Consumer) ifPresent 方法提供了有值后的消費邏輯而沒有值的邏輯沒有提供入口。新方法 ifPresentOrElse 彌補了這一缺陷

5. Optional 的使用誤區

Optional 很香但是也不能濫用。一個危險的舉動就是將 Optional 作為入參傳遞給方法。因為入參是不可控的,你無法保證入參中的 Optional 是否為 null。這恰恰違背了 Optional的本意。所以盡量在表達式中使用 Optional 或者在返回值中使用,而不是在方法的參數中使用 Optional 。

6. 總結

今天對 Optional 進行講解。從 Optional 的設計本意到其常用的方法。我們也對 Optional  Java 9 中的新 API 進行了介紹。另外 Optional 也不是萬能的,合理的使用才能發揮其優勢。希望今天的文章對你有用。


java培訓班:http://www.akpsimsu.com/java2019


注釋:本文內容來自公眾號碼農小胖哥

上一篇:web前端培訓 | 一文學會 Node.js 中的流

下一篇:應屆生去公司找個Java程序員的職位需要什么技能?

相關推薦

www.akpsimsu.com

有位老師想和您聊一聊

關閉

立即申請