做者:湯圓java
我的博客:javalover.ccgit
官人們好啊,我是湯圓,今天給你們帶來的是《Java8中的Optional操做》,但願有所幫助,謝謝github
文章純屬原創,我的總結不免有差錯,若是有,麻煩在評論區回覆或後臺私信,謝啦
最近看到有幾個粉絲了(竊喜),多的話我也不說了,歡迎加入咱們的榮華富貴你們庭數據庫
目的:Optional的出現主要是爲了解決null指針問題,也叫NPE(NullPointerException
)app
外形:Optional外形酷似容器(其實它就是一個容器),只是這個容器比較特殊,由於它只能存放一個對象,運氣很差的話這個對象仍是個nullide
操做:Optional從操做上來看,又跟前面的Stream流式操做很像,好比過濾filter - 提取map等函數
下面咱們用比較簡單的例子來對比着看下,Optional的一些基礎用法this
先來看下目錄編碼
Optional是一個容器,只能存放一個對象(可爲null)spa
Optional的出現是
optional
(可選的),意思就是說這個對象能夠爲空,能夠不爲空下面咱們用舊代碼和新代碼來對比着看(所謂的新舊是以Java8爲分割線)
案例1:現有C類,咱們要提取C.name屬性
public class OptionalDemo { private static final String DEFAULT_NAME = "javalover"; public static void main(String[] args) { // 傳入null,以身試法 getName(null); } // 取出c.name public static void getName(C c){ // 舊代碼 Java8以前 String name = (c!=null ? c.getName() : DEFAULT_NAME); System.out.println("old: "+name); // 新代碼 Java8以後(下面的三個操做方法後面會介紹,這裏簡單瞭解下) String nameNew = Optional // 工廠方法,建立Optional<C>對象,若是c爲null,則建立空的Optional<C>對象 .ofNullable(c) // 提取name,這裏要注意,即便c==null,這裏也不會拋出NPE,而是返回空的Optional<String>,因此在處理數據時,咱們不須要擔憂空指針異常 .map(c1->c1.getName()) // 獲取optional的屬性值,若是爲null,則返回給定的實參DEFAULT_NAME .orElse(DEFAULT_NAME); System.out.println("new: "+nameNew); } } class C{ private String name; public C(String name) { this.name = name; } // 省略getter/setter }
乍一看,好像Java8以前的舊代碼更合適啊,只須要一個三目運算符
再看Optional操做,發現並無那麼簡潔
是這樣的,若是隻是一層判斷,那普通的if判斷作起來更方便;
可是若是嵌套兩層呢,好比b.getC().getName()?
下面咱們就看下,兩層嵌套會怎麼樣
例子2:現多了一個B類(依賴C類),咱們要從對象B中提取C的屬性name,即b.getC().getName()
public static void getName2(B b){ // 舊代碼 String name = (b!=null ? ( b.getC()!=null ? b.getC().getName() : DEFAULT_NAME) : DEFAULT_NAME); // 新代碼 String nameNew = Optional .ofNullable(b) .map(b1->b1.getC()) .map(c1->c1.getName()) .orElse(DEFAULT_NAME); System.out.println(nameNew); } class B{ private C c; public B(C c) { this.c = c; } // 省略getter/setter }
此次不論是乍一看,仍是一直看,都是Optional更勝一籌
例子3:現多了一個A類(依賴B類),咱們要提取a.getB().getC().getName()
等等等,省略號
意思到就行,反正要說的就是單從判空來看的話,Optional確定是好過三目運算符的(if/else這裏就不舉了,它的嵌套只會更多)
由於Optional主要是操做數據(相似數據庫操做),因此咱們這裏從數據的角度來進行分析
這裏咱們能夠分爲三種操做:保存數據、處理數據、獲取數據
保存數據:
public static <T> Optional<T> of(T value)
:填充 T value 到 Optional 的屬性中;若是 value==null,則拋出NPEpublic static <T> Optional<T> ofNullable(T value)
:填充 T value 到 Optional 的屬性中;若是引用爲null,則填充nullpublic static<T> Optional<T> empty()
:單純地建立一個數據爲null的空Optional,即直接填充null到 Optional 的屬性中【不經常使用】處理數據:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
:提取Optional中屬性T的某個屬性值U,並將U填充到新的Optional中並返回public Optional<T> filter(Predicate<? super T> predicate)
:過濾Optional中屬性T的某個屬性值,符合條件則將T填充到新的Optional中並返回public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
:提取Optional中屬性T的某個屬性Optional<U>
,直接返回獲取數據:
public T orElse(T other)
:獲取數據,若是數據爲null,則返回T otherpublic T orElseGet(Supplier<? extends T> other)
:獲取數據,若是數據爲null,則經過函數式接口other返回一個新的數據Tpublic T get()
:獲取數據,若是數據爲null,則報NPE【不經常使用】上面這些操做中,不經常使用的就是get()和empty()
其餘的就不舉了,這裏主要說下map()和flatMap()
以下圖所示:
map()主要是提取Optional中的屬性C的屬性name,而後再包裝到新的Optional
輸入Optional<C>
, 輸出Optional<String>
(即Optional<c.name>)
String nameNew = Optional .ofNullable(c) .map(c1->c1.getName()) .orElse("xxx");
flatMap()主要是提取Optional中的屬性B的Optional<C>
屬性中的C的值,而後再包裝到新的Optional
輸入Optional<B>
,輸出Optional<C>
public class FlatMapDemo { private static final String DEFAULT_NAME = "javalover"; public static void main(String[] args) { getName(null); } // 取出 b.c.name public static void getName(B b){ C c = Optional .ofNullable(b) // 這裏扁平化處理,提取Optional<C>中的C // 若是用map,則返回的是Optional<Optional<C>> .flatMap(b->b.getC()) .orElse(new C("xxx")); System.out.println(c.getName()); } } class B{ private Optional<C> c; public Optional<C> getC() { return c; } public void setC(C c) { this.c = Optional.ofNullable(c); } } class C{ private String name; public C(String name) { this.name = name; } // 省略getter/setter }
從規範角度來說,是爲了代碼清晰,一看用Optional<T>
變量,就知道T可能爲null;
從編碼角度來說,主要是應用在非空判斷;可是實際場景的話,有兩個
// 取出c.name public static void getName(C c){ // 本身手動包裝 Optional<C> String nameNew = Optional .ofNullable(c) .map(c1->c1.getName()) .orElse(DEFAULT_NAME); System.out.println("new: "+nameNew); }
// 返回Optional<Car>,經過.orElse(defaultCar)就能夠獲取返回值,若是返回值爲null,還能夠設定一個默認值defaultCar Optional<Car> selectOne(SelectStatementProvider selectStatement);
沒它 VS 有它:看場景
核心操做:不經常使用的這裏就不寫了
of()
和ofNullable()
最後,感謝你們的觀看,謝謝
原創不易,期待官人們的三連喲