空指針異Optional常是致使Java應用程序失敗的最多見緣由。之前,爲了解決空指針異常,Google公司著名的Guava項目引入了Optional類,Guava經過使用檢查空值的方式來防止代碼污染,它鼓勵程序員寫更乾淨的代碼。受到Google Guava的啓發,Optional類已經成爲Java 8類庫的一部分。Optional其實是個容器:它能夠保存類型T的值,或者僅僅保存null。Optional提供不少有用的方法,這樣咱們就不用顯式進行空值檢測。java
Optional.of()或者Optional.ofNullable():建立Optional對象,差異在於of不容許參數是null,而ofNullable則無限制。程序員
Optional.empty():全部null包裝成的Optional對象:安全
isPresent():判斷值是否存在app
ifPresent(Consumer consumer):若是option對象保存的值不是null,則調用consumer對象,不然不調用ide
orElse(value):若是optional對象保存的值不是null,則返回原來的值,不然返回value函數
orElseGet(Supplier supplier):功能與orElse同樣,只不過orElseGet參數是一個對象spa
orElseThrow():值不存在則拋出異常,存在則什麼不作,有點相似Guava的Precoditions設計
filter(Predicate):判斷Optional對象中保存的值是否知足Predicate,並返回新的Optional。指針
map(Function):對Optional中保存的值進行函數運算,並返回新的Optional(能夠是任何類型)code
flatMap():功能與map()類似,差異請看以下代碼。flatMap方法與map方法相似,區別在於mapping函數的返回值不一樣。map方法的mapping函數返回值能夠是任何類型T,而flatMap方法的mapping函數必須是Optional。
1 Optional<Integer> optional1 = Optional.ofNullable(1); 2 3 Optional<Optional<String>> str1Optional = optional1.map((a) -> { 4 return Optional.<String>of("key" + a); 5 }); 6 7 Optional<String> str2Optional = optional1.flatMap((a) -> { 8 return Optional.<String>of("key" + a); 9 }); 10 11 System.out.println(str1Optional.get().get());// key1 12 System.out.println(str2Optional.get());// key1
Optional是Java8提供的爲了解決null安全問題的一個API。善用Optional可使咱們代碼中不少繁瑣、醜陋的設計變得十分優雅。
使用Optional,咱們就能夠把下面這樣的代碼進行改寫。
1 public static String getName(User u) { 2 if (u == null) { 3 return "unknow"; 4 } 5 return u.name; 6 }
不過,千萬不要改寫成這副樣子。
1 public static String getName(User u) { 2 Optinal<User> user = Optinal.ofNullable(u); 3 if (!user.isPresent()) { 4 return "unknow"; 5 } 6 return user.get().name; 7 }
這樣改寫非但不簡潔,並且其操做仍是和第一段代碼同樣。無非就是用isPresent方法來替代u==null。這樣的改寫並非Optional正確的用法,咱們再來改寫一次。
1 public static String getName(User u) { 2 return Optinal.ofNullable(u) 3 .map(user->user.name) 4 .orElse("unknow"); 5 }
這樣纔是正確使用Optional的姿式。那麼按照這種思路,咱們能夠安心的進行鏈式調用,而不是一層層判斷了。看一段代碼:
1 public static String getChampionName(Competion comp) throws testException { 2 if (comp != null) { 3 CompResult result = comp.getResult(); 4 if (result != null) { 5 User user = result.getUser(); 6 if (user != null) { 7 return user.getName(); 8 } 9 } 10 } 11 12 throw new testException("test error exception"); 13 }
因爲種種緣由(好比:比賽尚未產生冠軍、方法的非正常調用、某個方法的實現裏埋藏的大禮包等等),咱們並不能開心的一路comp.getResult().getChampion().getName()到底。而其餘語言好比kotlin,就提供了在語法層面的操做符加持:comp?.getResult()?.getChampion()?.getName()。因此講道理在Java裏咱們怎麼辦!
讓咱們看看通過Optional加持事後,這些代碼會變成什麼樣子。
1 public static String getChampionName(Competion comp) throws testException { 2 return Optinal.ofNullable(comp) 3 .map(c->c.getResult()) 4 .map(r->r.getUser()) 5 .map(u->u.getName()) 6 .orElseThrow(()->new testException("test error exception")); 7 }
這就很舒服了。Optional給了咱們一個真正優雅的Java風格的方法來解決null安全問題。雖然沒有直接提供一個操做符寫起來短,可是代碼看起來依然很爽很舒服。