java8新特性O(shè)ptional深度解析

public final classOptional{}

Optional是一個為了解決NullPointerException設(shè)計而生可以包含對象也可以包含空的容器對象异袄。封裝了很多對空處理的方法也增加了filter娇澎、map這樣的檢索利器媒抠,其中函數(shù)式編程會有種炫酷到爆的感覺渴析。

基礎(chǔ)測試用例對象:

public classJava8OptionalTest{

? ? List<String> stringList = null;

? ? ICar car = new WeiLaiCar();

}public classWeiLaiCarimplementsICar{

? ? Integer wheels = new Integer(4);

Api中提供的4種optional

最核心的當屬Optional對象辆憔,泛型的引入支持了所有對象類型焙畔,又增加對常用場景下的double\int\long進行擴展捎琐。重點介紹一下Optional對象的方法其他三個類似蓄髓。

public final class Optional<T> {

public final class OptionalDouble {

public final class OptionalInt {

public final class OptionalLong {

@FunctionalInterface

Predicate\Consumer\Supplier三個接口都是函數(shù)式接口

靜態(tài)方法of

privateOptional(){this.value =null;}

構(gòu)造方法被private叉庐,不能new但提供了of這樣的靜態(tài)方法去初始化類;

public static <T> Optionalof(T value){

? ? return new Optional<>(value);

}public static <T> OptionalofNullable(T value){

? ? return value == null ? empty() : of(value);

}publicstatic Optionalempty(){

? ? @SuppressWarnings("unchecked")

? ? Optional<T> t = (Optional<T>) EMPTY;

? ? return t;

}

1会喝、empty支持你去創(chuàng)建一個空的optional類陡叠,這樣的類直接get()會報錯:java.util.NoSuchElementException: No value present

2、of(x)傳入的對象不能為null肢执,而ofNullable(x)是支持傳入null的對象枉阵,一般用這兩個比較多。

present 方法

isPresent是用來判斷optional中對象是否為null预茄,ifPresent的參數(shù)是當對象不為null時執(zhí)行的lamdba表達式兴溜。

publicbooleanisPresent(){

? ? return value != null;

}publicvoidifPresent(Consumer consumer){

? ? if (value != null)

? ? ? ? consumer.accept(value);

}

示例詳解介紹了ifPresent特性:

Java8OptionalTest test = new Java8OptionalTest();

Optional<Java8OptionalTest> optional = Optional.of(test);

pringTest(optional.isPresent());//trueoptional.ifPresent( a -> pringTest(a.getCar().getClass().getName()));//com.ts.util.optional.WeiLaiCaroptional.ifPresent( a -> Optional.ofNullable(a.getStringList()).ifPresent(b -> pringTest("StringList:" + (b == null))));//第一級的ifPresent是存在test對象,所以執(zhí)行了lambda表達式耻陕,而第二級的ifPresent的stringList是null拙徽,所以沒有執(zhí)行表達式optional.ifPresent( a -> Optional.ofNullable(a.getCar()).ifPresent(b -> pringTest("car:" + (b == null))));//car:false//第二級ifPresent的car對象是存在的,所以第二級的表達式執(zhí)行了

map 方法

源碼提供了兩種map和flatMap诗宣。

map方法的參數(shù)是個當包含的對象不為null時才執(zhí)行的lambda表達式膘怕,返回該表達式執(zhí)行結(jié)果的封裝optional對象,同理支持鏈式調(diào)用召庞,逐層深入和遞歸遞進很像岛心;

flatMap區(qū)別在于lambda表達式的返回結(jié)果必須主動包裹Optinoal,否則報錯

public Optionalmap(Function mapper){

? ? Objects.requireNonNull(mapper);

? ? if (!isPresent())

? ? ? ? return empty();

? ? else {

? ? ? ? return Optional.ofNullable(mapper.apply(value));

? ? }

}public OptionalflatMap(Function> mapper){

? ? Objects.requireNonNull(mapper);

? ? if (!isPresent())

? ? ? ? return empty();

? ? else {

? ? ? ? return Objects.requireNonNull(mapper.apply(value));

? ? }

}

測試示例:

Java8OptionalTest test = new Java8OptionalTest();

Optional<Java8OptionalTest> optional = Optional.of(test);

Optional opt1 = optional.map( a -> a.getCar());

pringTest(opt1.get());//com.ts.util.optional.WeiLaiCar@5d6f64b1int wheel = 0;//傳統(tǒng)null判斷寫法if(test != null){

? ? if(test.getCar() != null){//實際業(yè)務里面層級也許會超過3層? ? ? ? wheel = test.getCar().getWheelCount();

? ? }

}

pringTest("傳統(tǒng):"+wheel);//傳統(tǒng):4Optional opt2 = optional.map( a -> a.getCar()).map(b -> b.getWheelCount());//Optional支持下的寫法pringTest("optinal:"+opt2.get());//optinal:4Optional opt3 = optional.map( a -> a.getStringList()).map(b -> b.size());

pringTest(opt3);//Optional.emptyOptional opt4 = optional.flatMap(a -> Optional.of(a.getCar()));//主動包裹Optional對象pringTest(opt4);//Optional[com.ts.util.optional.WeiLaiCar@5d6f64b1]Optional opt5 = optional.flatMap(a -> Optional.of(a.getCar())).flatMap(b -> Optional.ofNullable(b.getWheelCount()));

pringTest(opt5);//Optional[4]

filter 方法

源碼如下:

publicOptionalfilter(Predicate predicate){

? ? Objects.requireNonNull(predicate);

? ? if (!isPresent())

? ? ? ? return this;

? ? else? ? ? ? return predicate.test(value) ? this : empty();

}

filter方法傳入一個斷言語句條件的lambda表達式裁眯,返回一個原對象的optional包裝鹉梨,所以支持鏈式調(diào)用;只要記住這三點你便掌握如何使用了穿稳。

看下面的例子:

Java8OptionalTest test = new Java8OptionalTest();

Optional<Java8OptionalTest> optional = Optional.of(test);

Optional result = optional.filter( a -> a.getCar() != null).filter( b -> b.getClass().getName() != null);

pringTest(result.isPresent()? result.get().getClass().getName(): result.isPresent());//com.ts.util.Java8OptionalTestOptional result1 = optional.filter( a -> a.getStringList() != null);

pringTest(result1.get());//java.util.NoSuchElementException: No value present

orElse 方法

Api提供了三個方法存皂。

orElse 當optional內(nèi)對象為null就返回這個參數(shù),比較像很多默認值設(shè)置逢艘;

orElseGet 基本同orElse旦袋,區(qū)別是傳入?yún)?shù)支持lambda表達式,返回的就是表達式執(zhí)行結(jié)果它改;

orElseThrow 也是傳入lambda表達式疤孕,但是表達式是拋出異常

publicTorElse(T other){

? ? return value != null ? value : other;

}publicTorElseGet(Supplier<? extends T> other){

? ? return value != null ? value : other.get();

}public <X extends Throwable> TorElseThrow(Supplier<? extends X> exceptionSupplier)throwsX{

? ? if (value != null) {

? ? ? ? return value;

? ? } else {

? ? ? ? throw exceptionSupplier.get();

? ? }

}

測試用例如下:

Java8OptionalTest one = null;

Java8OptionalTest test = new Java8OptionalTest();

Optional<Java8OptionalTest> optional = Optional.ofNullable(one);

pringTest(optional);//Optional.emptypringTest(optional.orElse(test));//com.ts.util.Java8OptionalTest@5197848cpringTest(optional.orElseGet(() -> new Java8OptionalTest()));//com.ts.util.Java8OptionalTest@5d6f64b1pringTest(optional.orElseThrow(() -> new RuntimeException("orElseThrow")));//java.lang.RuntimeException: orElseThrow

覺得不錯請點贊支持,歡迎留言或進我的個人群855801563領(lǐng)取【架構(gòu)資料專題目合集90期】央拖、【BATJTMD大廠JAVA面試真題1000+】祭阀,本群專用于學習交流技術(shù)鹉戚、分享面試機會,拒絕廣告专控,我也會在群內(nèi)不定期答題抹凳、探討

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市伦腐,隨后出現(xiàn)的幾起案子赢底,更是在濱河造成了極大的恐慌,老刑警劉巖柏蘑,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幸冻,死亡現(xiàn)場離奇詭異,居然都是意外死亡咳焚,警方通過查閱死者的電腦和手機洽损,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來革半,“玉大人趁啸,你說我怎么就攤上這事《蕉瑁” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵旅掂,是天一觀的道長赏胚。 經(jīng)常有香客問我,道長商虐,這世上最難降的妖魔是什么觉阅? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮秘车,結(jié)果婚禮上典勇,老公的妹妹穿的比我還像新娘。我一直安慰自己叮趴,他們只是感情好割笙,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著眯亦,像睡著了一般伤溉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妻率,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天乱顾,我揣著相機與錄音,去河邊找鬼宫静。 笑死走净,一個胖子當著我的面吹牛券时,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播伏伯,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼橘洞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了舵鳞?” 一聲冷哼從身側(cè)響起震檩,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜓堕,沒想到半個月后抛虏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡套才,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年迂猴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片背伴。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡沸毁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出傻寂,到底是詐尸還是另有隱情息尺,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布疾掰,位于F島的核電站搂誉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏静檬。R本人自食惡果不足惜炭懊,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拂檩。 院中可真熱鬧侮腹,春花似錦、人聲如沸稻励。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钉迷。三九已至至非,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間糠聪,已是汗流浹背荒椭。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舰蟆,地道東北人趣惠。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓狸棍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親味悄。 傳聞我的和親對象是個殘疾皇子草戈,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Java 8自Java 5(發(fā)行于2004)以來最具革命性的版本。Java 8 為Java語言侍瑟、編譯器唐片、類庫、開發(fā)...
    huoyl0410閱讀 627評論 1 2
  • java8新特性 原創(chuàng)者:文思 一涨颜、特性簡介 速度更快 代碼更少费韭,增加了Lambda 強大的Stream API ...
    文思li閱讀 3,047評論 1 1
  • 感恩早上跟媽媽出去,買了兩個粽子庭瑰。我留了一個給哥哥星持,而不是一個人吃完。我越來越會照顧家人弹灭。祝福我更懂事督暂,祝福我的家...
    Daisy明閱讀 182評論 1 0
  • 自己回到家里想真機調(diào)試,可是真機調(diào)試時報錯:Could not find Developer Disk Image...
    指尖猿閱讀 206評論 0 0
  • 畫完眼線以后,可以用扁平的刷子沾取深色眼影穷吮,在眼線上按壓一下逻翁,再與眼影暈染結(jié)合,效果更自然哦捡鱼。
    睿睿Dora閱讀 84評論 0 0