作為程式員,你肯定遇到過NullPointerException, 這個異常對於初出茅廬的新人, 還是久經江湖的老手都是不可避免的痛, 可又是那麼的無能為力,為瞭解決它,你只能在使用某個值之前,對其進行判空處理。然而這樣會使得代碼變得臃腫不堪。幸好jdk8引入了optional來處理了null的問題 ...
作為程式員,你肯定遇到過NullPointerException, 這個異常對於初出茅廬的新人, 還是久經江湖的老手都是不可避免的痛, 可又是那麼的無能為力,為瞭解決它,你只能在使用某個值之前,對其進行判空處理。然而這樣會使得代碼變得臃腫不堪。幸好jdk8引入了optional來處理了null的問題,使得我們可以不再對null做過多的關心。
先展示jdk8之前的寫法
1 // First before jdk8 2 Long id = 0L; 3 User user = getUserById(id); 4 if (user != null) { 5 String name = user.getName(); 6 System.out.println("name=" + name); 7 }
如果不對方法拿到的user 進行空判斷,下麵獲取其屬性很容易就會出現空指針異常。
jdk 8 寫法
1 User userById = Optional.ofNullable(getUserById(id)).orElse(new User()); 2 String name = userById.getName(); 3 System.out.println("new name=" + name);
這種寫法就避免了空的判斷,代碼顯得很簡便
下麵介紹下 optional 的方法
1、首先是構造 of, ofNullable, empty
1 // empty 構建空的optional對象 2 Optional<Object> empty = Optional.empty(); 3 4 // of 構造user的optional 對象,user對象不為空, 如果為空,構建的時候就會報nullPointerException 5 User user = new User(); 6 Optional<User> userOptional = Optional.of(user); 7 8 // ofNull 構造optional對象,內部user如果為空,就構建空的optional對象 9 Optional<User> userOptionalOfNull = Optional.ofNullable(user); 10 11 Optional<Object> objectOptional = Optional.of(null); 12 System.out.println(objectOptional); 13 14 15 Exception in thread "main" java.lang.NullPointerException 16 at java.util.Objects.requireNonNull(Objects.java:203) 17 at java.util.Optional.<init>(Optional.java:96) 18 at java.util.Optional.of(Optional.java:108) 19 at com.zbb.jdk.jdk8Test.optional.OptionalOfTest.main(OptionalOfTest.java:32)
看下ofNullable 方法源碼
2、 獲取 ifPresent, get, isPresent
1 Optional<User> userOptional = Optional.ofNullable(getUserById(id)); 2 // isPresent 判斷optional對象是否存在,如果存在,返回true, 否則返回false 3 if(userOptional.isPresent()){ 4 // 已判斷存在 5 // get 如果創建的Optional中有值存在,則返回此值,否則拋出NoSuchElementException 6 User user = userOptional.get(); 7 System.out.println("name" + user.getName()); 8 } 9 10 // 創建的Optional中的值存在,則執行該方法的調用,否則什麼也不做 11 // ifPresent方法的參數是一個函數式介面, 該方法無返回值,可以直接用lambda表達式 12 userOptional.ifPresent(user -> System.out.println("name=" + user.getName()));
最開始的例子也可以用isPresent來這樣改,但是這樣和原先判空並沒有什麼區別,只是方法不同而已,本質沒區別,所以不推薦。看下這幾個方法的源碼
3、獲取 orElse, orElseGet, orElseThrow
1 Optional<User> userOptional = Optional.ofNullable(getUserById(id)); 2 3 //orElse 如果optional 有值就返回值,如果沒有就返回一個預設值 4 // 預設值就是我們創建的一個類 5 User user = userOptional.orElse(new User("xiaohong", "123456789")); 6 System.out.println("name=" + user.getName()); // name=xiaohong 7 8 //orElseGet 如果optional有值就返回值,如果沒有,就執行一個Supplier介面,返回生成的值 9 User userOrElseGet = userOptional.orElseGet(() -> new User("xiaohongGet", "123456789")); 10 System.out.println("name=" + userOrElseGet.getName()); //name=xiaohongGet 11 12 //orElseThrow 如果optional有值就返回值,如果沒有,就返回一個指定的Supplier介面生成的異常 13 User userElseThrow = userOptional.orElseThrow(() -> new Exception("userOptional 為空!")); 14 15 // 為空時,拋出的異常 16 Exception in thread "main" java.lang.Exception: userOptional 為空! 17 at com.zbb.jdk.jdk8Test.optional.OptionalOrElse.lambda$main$1(OptionalOrElse.java:29) 18 at java.util.Optional.orElseThrow(Optional.java:290) 19 at com.zbb.jdk.jdk8Test.optional.OptionalOrElse.main(OptionalOrElse.java:29)
看下源碼
orElseThrow 同理
4、過濾 filter
1 Optional<User> userOptional = Optional.ofNullable(new User("xiao", "123456")); 2 3 //optional中的值符合條件,則返回該optional對象,否則返回空的optional對象 4 User user = userOptional.filter(u -> NAME.equals(u.getName())).orElse(new User("不滿足", "")); 5 System.out.println("name=" + user.getName()); //name=xiao
5、轉化 map, flatMap
1 Optional<String> optional = Optional.ofNullable("zhang,san"); 2 3 //map optional對象存在就執行Funciton函數 4 // 可以返回任意類型的值 5 // 該函數式介面對optional對象中的值進行修改,返回修改後的值 6 Optional<String[]> optionalMap = optional.map(s -> s.split(",")); //Optional[[Ljava.lang.String;@19dfb72a] 7 8 // flatMap方法中的lambda表達式返回值必須是Optionl實例 9 Optional<String> optionalFlatMap = optional.flatMap(s -> Optional.of("lisi"));//Optional[lisi]
看源碼知道,map 和 flatmap 都是如果optional中的值存在,就對該值執行提供的Function函數調用,返回一個optional類型的值,否
則就返回一個空的optional對象。
最大的區別是map 函數執行之後是任意的類型數據,調用結束map 會再用optional對結果進行包裝,而flatmap 是執行完之後就是一個optional 實例 ,flatmap 不會對結果進行optional封裝。