1. 程式人生 > >Java8 Optional詳解

Java8 Optional詳解

在Java8中新增了一個Optional類,官方描述是該類是一個容器物件,其中可能包含一個空或非空的值。如果存在一個值,isPresent()將返回true,get()將返回該值。

錯誤使用姿勢

簡單的根據描述,我們認為Optional可以幫我們解決NPE問題,假設任務需求為獲取使用者的性別,那麼可以這樣寫:

Optional<User> user = ...
if(user.isPresent()) {
    return user.get().getSex();
} else {
    return null;
}

其實這樣並沒有改變原本的思維, 只是本能的認為該類是 User 例項的包裝, 這與下面的寫法沒有本質的區別:

User user = ...
if(user != null) {
    return user.getSex();
} else {
    return null;
}

正確使用姿勢

想要正確的使用,得知道有哪些方法,下面我列出一些常用的API:

Modifier and Type Method Description
static < T > Optional< T > empty() 返回一個空的Otptional例項
static < T > Optional< T > of(T value) 傳入的值必須非null,否則丟擲NPE
static < T > Optional< T > ofNullable(T value) 當傳入null時,返回空的Optional例項
< U > Optional< U > map(Function mapper) 如果值存在,則將所提供的對映函式應用於該函式,否則返回一個描述結果的可選項
T orElse(T other) 如果值存在返回該值,否則返回傳入的值
T orElseGet(Supplier other) 如果值存在返回該值,否則呼叫其他值並返回該呼叫的結果
void ifPresent(Consumer consumer) 當值存在時執行引數上的語句
Optional< T > filter(Predicate predicate) 當值存在且符合指定規則返回該值,否則返回null
< X extends Throwable> T orElseThrow(Supplier exceptionSupplier) 如果值存在返回該值,否則丟擲指定異常

前三個為構造方法,一般使用ofNullable即可,因為它能智慧的判斷引數是否為null,但是該方法也不是一勞永逸的,否則也沒必要外露另外兩個構造方法,如果我們明確的知道引數為非null或不允許任何null值的存在,可以使用of

對於其他方法,給出例子相信能很快理解:

/* ===== 得到User例項 ==== */

// 等價於 return user.isPresent() ? user.get() : null;
return user.orElse(null); 

// 等價於 return user.isPresent() ? user: getNewUser();
return user.orElseGet(() -> getNewUser());

/*
 等價於 
 if (user.isPresent()) { 
     System.out.println(user.get()); 
 }
 */
user.ifPresent(System.out::println);
/* ===== 得到User.sex ==== */

/*
 等價於:
 if(user.isPresent()) {
      return user.get().getSex();
 } else {
      return "男";
 }
*/
return user.map(u -> u.getSex()).orElse("男");

總結:使用 Optional 時儘量不直接呼叫 Optional.get() 方法, Optional.isPresent() 更應該被視為一個私有方法, 應使用像 Optional.orElse(), Optional.orElseGet(), Optional.map() 等這樣的方法。