你真的會用Optional嗎?

前言

Java8以前咱們在寫代碼的時候,常常會遇到返回null的狀況,若是這種狀況不加以判斷,你就會碰到NullPointerException(NPE)。而在Java8中,Optional類型是一種更好的表示缺乏返回值的形式。java

首先來看一段代碼,這多是之前大多數人的寫法web

private void getIsoCode( User user){
  if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
      Country country = address.getCountry();
      if (country != null) {
          String isocode = country.getIsocode();
          if (isocode != null) {
              isocode = isocode.toUpperCase();
          }
      }
    }
  }
}
複製代碼

而當咱們有了Optional以後,上面的代碼就能夠縮減很大一部分,答案我會在後面給出。數據庫

我見過有人的寫法是這樣的安全

Optional<T> optionalValue = ... ;
optionalValue.get().someMethod();

或者

if(optionalValue.isPresent()) {
  optionalValue.get().someMethod();
}
複製代碼

它並不比下面的方式安全app

T value = ... ;
value.someMethod();

或者

if(value != null) {
  value.someMethod();
}
複製代碼

若是你在你的代碼中出現了上面使用Optional的片斷,那麼你該好好優化下了。函數

其實高效使用Optional的關鍵在於,使用一個 接受正確值或者返回另外一個替代值 的方法。性能

建立Optional

// 建立一個空的Optional實例
public static<T> Optional<T> empty() {
  Optional<T> t = (Optional<T>) EMPTY;
  return t;
}

// 根據傳入的值建立一個非空的實例, value不能爲空,不然拋出NPE
 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);
}
複製代碼

上面的三個方法就是咱們構造Optional的途徑,能夠看到實際上Optional是對value的封裝。
須要注意的是ofNullableof的區別,推薦使用ofNullable方法優化

其餘經常使用方法

  1. boolean isPresent()
    判斷value是否存在spa

  2. Optional filter(Predicate predicate)
    判斷value是否知足條件code

  3. Optional<U> map(Function<? super T, ? extends U> mapper)
    對其中的value執行一個函數,將其變成另外一個值。返回的值會被Optional.ofNullable封裝

  4. Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
    也是對其中的value執行一個函數,注意和map的區別在於,執行這個函數返回的值是Optional類型,返回的值不會被封裝。

  5. orElse(T other)
    當value存在時,返回value,不存在時返回other

  6. orElseGet(Supplier<? extends T> other)
    和orElse同樣,只是這裏的參數是經過傳入的function來決定的

  7. T orElseThrow
    當value存在時,返回value,不存在時拋出異常

代碼優化

開頭給出的代碼就能夠被優化爲下面的代碼

 String isoCode = Optional.ofNullable(user)
    .map(User::getAddress)  //Optional<Address>
    .map(Address::getCountry)  //Optional<Country>
    .map(Country::getIsocode)  // Optional<String>
    .orElse("empty");
複製代碼

不過有一點須要注意的是orElse和orElseGet的區別在於,不管是否知足條件orElse中的方法始終會被執行,而orElseGet中的只有當value爲空時纔會執行。

Optional.ofNullable(user)
    .map(User::getAddress)
    .map(Address::getCountry)
    .map(Country::getIsocode)
    .orElse(getIsoCode());
複製代碼

你可能以爲沒什麼,可是若是你的業務中獲取這個值要去數據庫查詢,那麼每一次只要運行這個代碼就都要去查詢,這樣就形成了沒必要要的性能損失了,仍是一個很大的問題的。

技術總結

  1. Optional是爲了更優雅的判斷null而誕生的,可是並不表明有null的地方必定就要用Optional代替
  2. Optional通常用於方法返回值,不用於屬性(沒法被序列化)
  3. Optional用於多層次null判斷有奇效
相關文章
相關標籤/搜索