ullPointerException 是編碼過程當中必需要處理的防護式檢查,咱們可能用if(null != user) 或者 Objects.isNull(user)等方式處理,再jdk1.8以後,你能夠優雅的處理這個問題app
定義
Optional 類是一個能夠爲null的容器對象。若是值存在則isPresent()方法會返回true,調用get()方法會返回該對象。
Optional 是個容器:它能夠保存類型T的值,或者僅僅保存null。Optional提供不少有用的方法,這樣咱們就不用顯式進行空值檢測。
Optional 類的引入很好的解決空指針異常。函數
方法實例演示
例舉幾個經常使用的函數,而後進行實際使用分析this
of編碼
//建立一個值爲張三的String類型的Optional
Optional<String> ofOptional = Optional.of("李四");指針
//若是咱們用of方法建立Optional對象時,所傳入的值爲null,則拋出NullPointerException
Optional<String> nullOptional = Optional.of(null);code
of的用法實際上就是靜態工廠方法,示例以下:對象
@Data接口
public class Card { private String name; private String number; private Card() {} private Card(String name,String number) { this.name = name; this.number = number; } public static Card of() { return new Card(); } public static Card of(String name,String number) { return new Card(name,number); } }
目前,靜態工廠方法比較流行,若是目標類類不須要子類化,很是推薦使用這種方式。
get開發
若是建立的Optional對象中有值存在則返回此值,若是沒有值存在,則會拋出 NoSuchElementException異常
ofNullableget
//爲指定的值建立Optional對象,無論所傳入的值爲null不爲null,建立的時候都不會報錯
Optional<String> nullOptional = Optional.ofNullable(null); Optional<String> noNullOptional = Optional.ofNullable("李四"); System.out.println(nullOptional.get());//拋出異常 NoSuchElementException: No value present System.out.println(noNullOptional.get());//李四
empty
//建立一個空的String類型的Optional對象 Optional<String> emptyOptional = Optional.empty(); System.out.println(emptyOptional .get());//拋出異常 NoSuchElementException
orElse
存在就返回該值,不存在就返回默認值
Optional<String> stringOptional = Optional.of("張三"); System.out.println(stringOptional.orElse("zhangsan"));//張三 Optional<String> emptyOptional = Optional.empty(); System.out.println(emptyOptional.orElse("李四"));//李四
orElseThrow
若是建立的Optional中有值存在,則返回此值,不然拋出一個由指定的Supplier接口生成的異常
Optional<String> stringOptional = Optional.of("張三"); System.out.println(stringOptional.orElseThrow(Exception::new));
map
若是建立的Optional中的值存在,對該值執行提供的Function函數調用
map方法執行傳入的lambda表達式參數對Optional實例的值進行修改,修改後的返回值仍然是一個Optional對象
Optional<String> stringOptional = Optional.of("張三"); System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("不能爲空")); stringOptional = Optional.empty(); System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("不能爲空"));
filter
若是建立的Optional中的值知足filter中的條件,則返回包含該值的Optional對象,不然返回一個空的Optional對象
Optional<String> stringOptional = Optional.of("張三"); System.out.println(stringOptional.filter(e -> e.equals("張三")));//Optional[張三] System.out.println(stringOptional.filter(e -> !e.equals("張三")).orElse("李四"));//張三 stringOptional = Optional.empty(); System.out.println(stringOptional.filter(e -> e.equals("張三")).orElse("李四"));//李四
flagMap
flatMap與map(Funtion)方法相似,區別在於flatMap中的mapper返回
值必須是Optional,map方法的mapping函數返回值能夠是任何類型T
Optional<String> stringOptional = Optional.of("張三"); System.out.println(stringOptional.flatMap(e -> Optional.of("李四")).orElse("不能爲空"));
可能看到這兒以後並無感受到多麼好用,該寫的判斷仍是要寫,我們繼續
實際使用
Person p = new Person("李四",11);//若是 p = null 拋出"年齡不能爲空"異常 Integer orElseThrow = Optional.ofNullable(p) .map(s -> s.getAge())//返回參數爲年齡的function .map(b ->b + 1)//返回參數爲年齡+ 1 的function .filter(m -> m.compareTo(10) == 1)//若是年齡大於10則保留,小於10則過濾掉 .orElseThrow(() -> new Exception("年齡不合法"));//若是爲空則拋出該異常 System.out.println(orElseThrow);//12
這種用法能夠對單條或多條(配合foreach)能簡化大量代碼和判斷,經過拋出統一異常,使用異常攔截器進行攔截,統一處理,能很大程度上提升開發效率和代碼閱讀性。