身爲一名Java程序員,你們可能都有這樣的經歷:調用一個方法獲得了返回值卻不能直接將返回值做爲參數去調用別的方法。咱們首先要判斷這個返回值是否爲null,只有在非空的前提下才能將其做爲其餘方法的參數。這正是一些相似Guava的外部API試圖解決的問題。一些JVM編程語言好比Scala、Ceylon等已經將對在覈心API中解決了這個問題。html
新版本的Java,好比Java 8引入了一個新的Optional類。Optional類的Javadoc描述以下:git
這是一個能夠爲null的容器對象。若是值存在則isPresent()方法會返回true,調用get()方法會返回該對象。程序員
本文會逐個探討Optional類包含的方法,並經過一兩個示例展現如何使用。github
爲非null的值建立一個Optional。
of方法經過工廠方法建立Optional類。須要注意的是,建立對象時傳入的參數不能爲null。若是傳入參數爲null,則拋出NullPointerException 。編程
爲指定的值建立一個Optional,若是指定的值爲null,則返回一個空的Optional。app
若是值存在返回true,不然返回false。編程語言
若是Optional有值則將其返回,不然拋出NoSuchElementException。函數
若是Optional實例有值則爲其調用consumer,不然不作處理google
若是有值則將其返回,不然返回指定的其它值。3d
orElseGet與orElse方法相似,區別在於獲得的默認值。orElse方法將傳入的字符串做爲默認值,orElseGet方法能夠接受Supplier接口的實現用來生成默認值
若是有值則將其返回,不然拋出supplier接口建立的異常。
在orElseGet方法中,咱們傳入一個Supplier接口。然而,在orElseThrow中咱們能夠傳入一個lambda表達式或方法,若是值不存在來拋出異常。
若是有值,則對其執行調用mapping函數獲得返回值。若是返回值不爲null,則建立包含mapping返回值的Optional做爲map方法返回值,不然返回空Optional。
map方法用來對Optional實例的值執行一系列操做。經過一組實現了Function接口的lambda表達式傳入操做。
若是有值,爲其執行mapping函數返回Optional類型返回值,不然返回空Optional。
flatMap方法與map方法相似,區別在於mapping函數的返回值不一樣。map方法的mapping函數返回值能夠是任何類型T,而flatMap方法的mapping函數必須是Optional。
參照map函數,使用flatMap重寫的示例以下:
若是有值而且知足斷言條件返回包含該值的Optional,不然返回空Optional。
這裏能夠傳入一個lambda表達式。對於filter函數咱們應該傳入實現了Predicate接口的lambda表達式。
/* of */ //調用工廠方法建立Optional實例 Optional<String> name = Optional.of("YanWei"); //傳入參數爲null,拋出NullPointerException. //Optional<String> someNull = Optional.of(null); /*opNullable*/ Optional empty = Optional.ofNullable(null); /*isPresent*/ if (name.isPresent()) { System.out.println(name.get());//輸出YanWei } /*get*/ try { System.out.println(empty.get()); } catch (NoSuchElementException ex) { System.err.println(ex.getMessage()); } /*ifPresent*/ name.ifPresent((value) -> { System.out.println("The length of the value is: " + value.length()); }); /*orElse*/ System.out.println(empty.orElse("There is no value present!")); System.out.println(name.orElse("There is some value!")); /*orElseGet*/ System.out.println(empty.orElseGet(() -> "Default Value")); System.out.println(name.orElseGet(String::new)); /*orElseThrow*/ try { empty.orElseThrow(IllegalArgumentException::new); } catch (Throwable ex) { System.out.println("error:" + ex.getMessage()); } /*map*/ Optional<String> upperName = name.map((value) -> value.toUpperCase()); System.out.println(upperName.orElse("No value found")); /*flatMap*/ upperName = name.flatMap((value) -> Optional.of(value.toUpperCase())); System.out.println(upperName.get()); /*filter*/ List<String> names = Arrays.asList("YanWei","YanTian"); for(String s:names) { Optional<String> nameLenLessThan7 = Optional.of(s).filter((value) -> value.length() < 7); System.out.println(nameLenLessThan7.orElse("The name is more than 6 characters")); }