1、JAVA8 之 Optional 詳解


前言  

  相信不少小伙伴已經被java的NPE(Null Pointer Exception)所謂的空指針異常搞的頭昏腦漲, 有大佬說過“防止 NPE,是程序員的基本修養。”但是修養歸修養,也是我們程序員最頭疼的問題之一,那么我們今天就要盡可能的利用Java8的新特性 Optional來盡量簡化代碼同時高效處理NPE(Null Pointer Exception 空指針異常)

認識 Optional

1、ofNullable 、orElse、isPresent 和 ifPresent

  Java 8 提供了判空寫法:

Optional.ofNullable(對象).orElse(為空時的邏輯).ifPresent(不為空是的邏輯);
boolean isNull = Optional.ofNullable(對象).isPresent(); // 如果為空返回 false;不為空返回 true

  ofNullable 中的對象是一個可為空的對象(這個對象可以包含任意類型:Integer、Object、List、Map 等等),如果為空則執行 orElse 里面的邏輯,不為空則執行 ifPresent 里面的邏輯;也可以直接通過 isPresent() 來判斷當前對象是否為空。直接上例子吧:

//求字符串 s 的長度( 為空的時候返回0 )
String str = getKey();
if (StringUtils.isBlank(str)) {
    return 0;
} else {
    return str.length();
}
// 新版 JDK 用法
return Optional.ofNullable(str).orElse("").length();
// 或者
if (Optional.ofNullable(str).isPresent()) {
    return str.length();
}
// 或者
Optional.ofNullable(str).ifPresent(s -> System.out.println("長度"+s.length());

  循環遍歷List 集合

// 原來常規寫法
List<String> list = getList();

if (list != null) {
  for(String s: list){
      System.out.println(s);
  }
}
// 新版 JDK 寫法
Optional.ofNullable(list).orElse(new ArrayList<>()).forEach(o -> System.out.println(o));

2、filter

  用於對給定的對象進行過濾

  filter()方法大致意思是,接受一個對象,然后對他進行條件過濾,如果條件符合則返回Optional對象本身,如果不符合則返回空Optional

Person person=new Person();
person.setAge(2);
Optional.ofNullable(person).filter(p -> p.getAge()>50)

  再看一個根據基本的電子郵箱驗證來決定接受或拒絕 User(用戶) 的示例

@Test
public void whenFilter_thenOk() {
    User user = new User("anna@gmail.com", "1234");
    Optional<User> result = Optional.ofNullable(user)
      .filter(u -> u.getEmail() != null && u.getEmail().contains("@"));

    assertTrue(result.isPresent());
}

  如果通過過濾器測試,result 對象會包含非空值。

3、map

  map()方法將對應Funcation函數式接口中的對象,進行二次運算,封裝成新的對象然后返回在Optional中

Person person1=new Person();
person.setAge(2);
// 返回具體內容
String optName = Optional.ofNullable(person).map(p -> person.getName()).orElse("name為空");
// 返回到 optional 中
Optional<Object> optName = Optional.ofNullable(person).map(p -> Optional.ofNullable(p.getName()).orElse("name為空"));

4、orElseThrow()

  這個我個人在實戰中也經常用到這個方法,方法作用的話就是如果為空,就拋出你定義的異常,如果不為空返回當前對象,在實戰中所有異常肯定是要處理好的,為了代碼的可讀性

//簡單的一個查詢
Member member = memberService.selectByPhone(request.getPhone());
Optional.ofNullable(member).orElseThrow(() -> new ServiceException("沒有查詢的相關數據"));

差異對比

1、orElse() 和 orElseGet() 的不同之處

  乍一看,這兩種方法似乎起着同樣的作用。然而事實並非如此。我們創建一些示例來突出二者行為上的異同。

@Test
public void givenEmptyValue_whenCompare_thenOk() {
    // 第一種情況
    User user = null;
    // 第二種情況
    User user = new User("john@gmail.com", "1234");
    logger.debug("Using orElse");
    User result = Optional.ofNullable(user).orElse(createNewUser());
    logger.debug("Using orElseGet");
    User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
}

private User createNewUser() {
    logger.debug("Creating New User");
    return new User("extra@gmail.com", "1234");
}

  打印輸出結果如下:

// 第一種情況
Using orElse
creating user
Using orElseGet
creating user

// 第二種情況
Using orElse
creating user
Using orElseGet

  這個示例中,兩個 Optional  對象都包含非空值,兩個方法都會返回對應的非空值。不過,orElse() 方法仍然創建了 User 對象。與之相反,orElseGet() 方法不創建 User 對象。

  在執行較密集的調用時,比如調用 Web 服務或數據查詢,這個差異會對性能產生重大影響

  且需要注意:orElse 內部可以直接寫對應的方法或函數;orElseGet 內部必須要有對應的參數即使空也需要寫一個空的括號,注意對比下:

User result = Optional.ofNullable(user).orElse(createNewUser());
User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM