天天看點

java8新特性 Optional總述類聲明類常用的方法Optional 執行個體Optional在SpringBoot中的應用之一另附一張Optional的API

Java 8 Optional 類

  • 總述
  • 類聲明
  • 類常用的方法
  • Optional 執行個體
  • Optional在SpringBoot中的應用之一
  • 另附一張Optional的API

總述

Optional 為java8的新特性

Optional 類是一個可以為null的容器對象。如果值存在則isPresent()方法會傳回true,調用get()方法會傳回該對象。

Optional 是個容器:它可以儲存類型T的值,或者僅僅儲存null。Optional提供很多有用的方法,這樣我們就不用顯式進行空值檢測。

Optional 類的引入很好的解決空指針異常。

類聲明

java.util.optional類的聲明

public filnal class Optional extends Object

類常用的方法

序号 方法 描述
1 static Optional empty() 傳回空的 Optional 執行個體。
2 boolean equals(Object obj) 判斷其他對象是否等于 Optional。
3 Optional filter(Predicate<? super predicate>) 如果值存在,并且這個值比對給定的 predicate,傳回一個Optional用以描述這個值,否則傳回一個空的Optional。
4 Optional flatMap(Function< ? Super T>,Optional mapper) 如果值存在,傳回基于Optional包含的映射方法的值,否則傳回一個空的Optional
5 T get() 如果在這個Optional中包含這個值,傳回值,否則抛出異常:NoSuchElementException
6 boolean isPresent() 如果值存在則方法會傳回true,否則傳回 false。
7 static Optional of(T value) 傳回一個指定非null值的Optional。
8 static Optional ofNullable(T value) 如果為非空,傳回 Optional 描述的指定值,否則傳回空的 Optional。
9 T orElse(T other) 如果存在該值,傳回值, 否則傳回 other。
10 T orElseGet(Supplier<? extends T> other) 如果存在該值,傳回值, 否則觸發 other,并傳回 other 調用的結果。
11 T orElseThrow(Supplier<? extends X> exceptionSupplier) 如果存在該值,傳回包含的值,否則抛出由 Supplier 繼承的異常

Optional 執行個體

import java.util.Optional;
 
public class Java8Tester {
   public static void main(String args[]){
   
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
        
      // Optional.ofNullable - 允許傳遞為 null 參數
      Optional<Integer> a = Optional.ofNullable(value1);
        
      // Optional.of - 如果傳遞的參數是 null,抛出異常 NullPointerException
      Optional<Integer> b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional<Integer> a, Optional<Integer> b){
    
      // Optional.isPresent - 判斷值是否存在
        
      System.out.println("第一個參數值存在: " + a.isPresent());
      System.out.println("第二個參數值存在: " + b.isPresent());
        
      // Optional.orElse - 如果值存在,傳回它,否則傳回預設值
      Integer value1 = a.orElse(new Integer(0));
        
      //Optional.get - 擷取值,值需要存在
      Integer value2 = b.get();
      return value1 + value2;
   }
}
           

輸出結果為:

$ javac Java8Tester.java

$ java Java8Tester

第一個參數值存在: false

第二個參數值存在: true

10

示例重點解析:正常情況為value1 + value2=null+10會報錯,使用Optional後可以計算值

Optional在SpringBoot中的應用之一

Spring Boot 2.0中,在将原來的泛型改為了Optional,旨在讓我們的代碼更簡潔。

Optional findById(ID var1)

實踐

Optional

很簡單的一個類,點開它的源代碼,其中所有的方法都是與null相關聯的。

java8新特性 Optional總述類聲明類常用的方法Optional 執行個體Optional在SpringBoot中的應用之一另附一張Optional的API

這是一個簡化我們處理null的類。

它就是一個容器,其中有我們想要的對象,但是該對象有時候會是空,是以我們需要使用Optional封裝好的方法來擷取需要的對象。進而很好地避免了空指針異常。

錯誤示範

我看到網上很多人這麼寫:catRepository.findById(id).get();

下面是Spring Boot 1.5的寫法,那請問:如果上面的寫法是正确的,那為什麼還要大費周章設計一個Optional呢?

catRepository.findOne(id);

分析

通過get是能擷取到我們需要的對象。

但是看看get的源代碼,這樣寫,抛出了NoSuchElementException異常,這個異常我們沒法在全局中處理它。

public T get() {   
	if (value == null) {     
	throw new NoSuchElementException("No value present");   
	}   
return value; } 
           

因為NoSuchElementException覆寫的範圍太廣了,隻要是Optional中有null就會抛出NoSuchElementException,很多情況下都會造成這種異常,那我們究竟要給使用者一個什麼樣的提示資訊好呢?最後還是給出500伺服器異常,那異常處理的意義何在呢?

是以我們需要用Optional來抛出一個有特定範圍的能被全局準确處理的異常。

Cat cat = catRepository.findOne(id); 
if (null == cat) {   
throw new EntityNotFoundException("該實體找不到"); 
} 
return cat; 
           

思想都是一樣,我們不過是用一種更簡潔的寫法實作上面的功能。

實作

沒錯,就像下面一樣,我們隻需要一行代碼!

public Cat findById(Long id) {   
return catRepository.findById(id).orElseThrow(EntityNotFoundException::new); } 
           

findById傳回一個Optional,然後調用該對象的orElseThrow方法。

orElseThrow方法,如果存在,傳回包含的值,否則抛出異常。

該方法的參數是一個lamda表達式。這裡就不深究lamda表達式的幾種類型了,如果感興趣可以自行研究下Function、Consumer、Predicate、Supplier這四個函數式接口的差別。

是以傳一個lamda表達式進去,然後IDEA會給出警告:

java8新特性 Optional總述類聲明類常用的方法Optional 執行個體Optional在SpringBoot中的應用之一另附一張Optional的API

Can be replaced with method reference

該lamda表達式能被一個方法引用代替,Alt + Enter,我們最終的代碼就長這樣:

java8新特性 Optional總述類聲明類常用的方法Optional 執行個體Optional在SpringBoot中的應用之一另附一張Optional的API

這裡的::是lamda表達式的一種簡寫,是Java8中的新特性,看着可能有點奇怪,原來,編譯器比程式員聰明多了。

異常處理

@RestControllerAdvice
public class GlobalExceptionHandler {    
 @ExceptionHandler(EntityNotFoundException.class)   
 public ResponseEntity<String> entityNotFoundHandler() {    
  return new ResponseEntity<>("您要找的實體不存在", HttpStatus.NOT_FOUND);   } } 
           

寫個控制器增強,全局處理異常,這裡的RestControllerAdvice又是一個組合注解:

處理異常,同時以Json的格式傳回。

另附一張Optional的API

java8新特性 Optional總述類聲明類常用的方法Optional 執行個體Optional在SpringBoot中的應用之一另附一張Optional的API