在某些狀況下,首先要判斷某個參數或者某個方法的返回值是否爲null,才能繼續操做該參數。對於某些鏈式操做須要屢次經過if語句判斷是否爲空,才能確保不拋出NullPointerException,這段非空判斷的代碼顯得很是冗長和噁心。好比下面這段代碼:java
String isoCode = "default"; if (user != null) { Address address = user.getAddress(); if (address != null) { Country country = address.getCountry(); if (country != null) { isocode = country.getIosCode(); if (isocode != null) { isocode = isocode.toUpperCase(); } } } }
在java 8裏,JDK引入了一個Optional類,該類是一個能夠爲null的容器對象。若是值存在則isPresent()方法會返回true,調用get()方法會返回該對象。經過本文的學習,咱們看下如何經過Optional類重寫上面那段判空代碼。ios
接下來,咱們一塊兒學習Optional類的初始化和它裏面的方法。lambda表達式和四個基本函數式接口是本文的基礎,能夠經過 java8 -函數式編程之Lambda表達式 和 java8 -函數式編程之四個基本接口 充分了解。編程
Optional類的構造方法是私有方法,因此只能經過它的靜態工廠方法進行初始化。它的初始化方法有以下四種:app
(1) <T> Optional<T> of (T value) :爲非null的值建立一個Optional。若是傳入參數爲null,拋出NullPointerException。函數式編程
//調用工廠方法建立Optional實例 Optional<String> name = Optional.of("hello"); //傳入參數爲null,拋出NullPointerException. Optional<String> someNull = Optional.of(null);
(2)<T> Optional<T> ofNullable (T value) :爲指定的值建立一個Optional,若是指定的值爲null,則返回一個空的Optional。它和 of 的區別是能夠傳null值。在它的實現代碼中,若是傳的值爲null,會調用另外一個靜態工廠方法 empty 獲取一個Optional對象。函數
Optional empty = Optional.ofNullable(null);
(3)<T> Optional<T> empty () :ofNullable靜態工廠方法,傳null值時的實現,返回一個空的Optional。學習
(1)isPresent :若是值存在返回true,不然返回false。測試
// false Optional<String> empty = Optional.ofNullable(null); System.out.println(empty.isPresent()); // true Optional<String> optionalS2 = Optional.of(s2); System.out.println(optionalS2.isPresent());
(2)get:若是Optional有值則將其返回,不然拋出NoSuchElementExceptionspa
//獲取hello Optional.of("hello").get(); //拋出NoSuchElementException Optional.empty().get();
(3)void ifPresent (Consumer<? super T> consumer) :若是Optional實例有值則調用consumer,不然不作處理。.net
//調用ifPresent方法裏面的consumer Optional.of("hello") .ifPresent(System.out::println);
(4)orElse:若是有值則將其返回,不然返回指定的其它值
//輸出:null System.out.println(Optional.empty().orElse("null")); //輸出:hello System.out.println(Optional.of("hello").orElse("null"));
(5)T orElseGet (Supplier<? extends T> other) :orElseGet與orElse方法相似,區別在於獲得的默認值。orElse方法將傳入的字符串做爲默認值,orElseGet方法能夠接受 Supplier接口 的實現用來生成默認值。
//輸出null System.out.println(Optional.empty().orElseGet(() -> "null")); //輸出hello System.out.println(Optional.of("hello").orElseGet(() -> "null"));
(6)<X extends Throwable> T orElseThrow (Supplier<? extends X> exceptionSupplier) throws X :若是有值則將其返回,不然拋出supplier接口建立的異常。
//拋出exception try { Optional.empty().orElseThrow(()->new Exception("爲空")); } catch (Exception e) { e.printStackTrace(); }
(7)<U> Optional<U> map (Function<? super T, ? extends U> mapper) :若是參數 mapper 有值,則調用map方法執行mapper參數的Function方法獲得返回值。若是mapper的返回值不爲null,則建立包含mapping返回值的Optional做爲map方法返回值,不然返回空Optional。若是傳入的mapper參數是null,拋出NullPointerException。
//輸出 JACK Optional<String> stringOptional = Optional.of("jack").map((value) -> value.toUpperCase()); System.out.println(stringOptional.orElse("default")); //輸出 default Optional<String> stringOptional1 = Optional.of("jack").map((value) -> null); System.out.println(stringOptional1.orElse("default")); //輸出 default,而且不會調用mapper String s2 = null; Optional<String> stringOptional2 = Optional.ofNullable(s2).map((value) -> value.toUpperCase()); System.out.println(stringOptional2.orElse("default")); //若是參數mapper爲null,拋NullPointerException異常 try { String s3 = null; Optional<String> stringOptional3 = Optional.ofNullable(s3).map(null); System.out.println(stringOptional3.orElse("default")); } catch (Exception e) { }
(8)<U> Optional<U> flatMap (Function<? super T, Optional<U>> mapper) :flatMap與map方法相似,區別在於flatMap中的mapper返回值必須是Optional。調用結束時,flatMap不會對結果用Optional封裝。
//flatMap,輸出 JACK Optional<String> stringOptional4 = Optional.of("jack").flatMap((value) -> Optional.ofNullable(value.toUpperCase())); System.out.println(stringOptional4.orElse("default")); //flatMap,輸出 default Optional<String> stringOptional5 = Optional.of("jack").flatMap((value) -> Optional.ofNullable(null)); System.out.println(stringOptional5.orElse("default")); //flatMap,輸出 default,而且不會調用mapper String s6 = null; Optional<String> stringOptional6 = Optional.ofNullable(s6).flatMap((value) -> Optional.ofNullable(value.toUpperCase())); System.out.println(stringOptional6.orElse("default")); //flatMap 若是map的參數mapper爲null,拋NullPointerException異常 try { String s7 = null; Optional<String> stringOptional7 = Optional.ofNullable(s7).flatMap(null); System.out.println(stringOptional7.orElse("default")); } catch (Exception e) { System.out.println("出錯了"); }
(9)Optional<T> filter (Predicate<? super T> predicate) :若是有值而且知足斷言條件返回包含該值的Optional,不然返回空Optional。
//輸出default String filterString = Optional.of("hugo") .filter(s -> "jack".equals(s)) .orElse("default"); System.out.println(filterString); //輸出hugo String filterString2 = Optional.of("hugo") .filter(s -> "hugo".equals(s)) .orElse("default"); System.out.println(filterString2); //輸出default,斷言接口裏面的語句不會執行 String nullableString = null; String filterString3 = Optional.ofNullable(nullableString) .filter(s -> { System.out.println("測試是否調用"); return "jack".equals(s); }) .orElse("default"); System.out.println(filterString3);
通過上面學習Optional的相關API,已經對它有了必定的瞭解。下面,咱們運用上面的知識解決在前言中遺留的問題。
ioscode = Optional.ofNullable(user) .map(u -> u.getAddress()) .map(addr -> addr.getCountry()) .map(country -> country.getIosCode()) .map(String::toUpperCase) .orElse("default");
從上面的學習能夠知道,只有Optional是empty的,map方法不會被調用。
Java 8 函數式編程系列