一、JDK8中Optional的方法使用介紹
空指針異Optional常是導致Java應用程序失敗的最常見原因。以前,為了解決空指針異常,Google公司著名的Guava項目引入了Optional類,Guava通過使用檢查空值的方式來防止代碼污染,它鼓勵程序員寫更干凈的代碼。受到Google Guava的啟發,Optional類已經成為Java 8類庫的一部分。Optional實際上是個容器:它可以保存類型T的值,或者僅僅保存null。Optional提供很多有用的方法,這樣我們就不用顯式進行空值檢測。
Optional.of()或者Optional.ofNullable():創建Optional對象,差別在於of不允許參數是null,而ofNullable則無限制。
Optional.empty():所有null包裝成的Optional對象:
isPresent():判斷值是否存在
ifPresent(Consumer consumer):如果option對象保存的值不是null,則調用consumer對象,否則不調用
orElse(value):如果optional對象保存的值不是null,則返回原來的值,否則返回value
orElseGet(Supplier supplier):功能與orElse一樣,只不過orElseGet參數是一個對象
orElseThrow():值不存在則拋出異常,存在則什么不做,有點類似Guava的Precoditions
filter(Predicate):判斷Optional對象中保存的值是否滿足Predicate,並返回新的Optional。
map(Function):對Optional中保存的值進行函數運算,並返回新的Optional(可以是任何類型)
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
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安全問題。雖然沒有直接提供一個操作符寫起來短,但是代碼看起來依然很爽很舒服。
