Java8 由Oracle在2014年發(fā)布奄抽,是繼Java5之后最具革命性的版本爆阶。
Java8吸收其他語言的精髓帶來了函數(shù)式編程窍育,lambda表達(dá)式遂铡,Stream流等一系列新特性,學(xué)會(huì)了這些新特性爬泥,可以讓你實(shí)現(xiàn)高效編碼優(yōu)雅編碼柬讨。
有個(gè)小故事:null引用最早是由英國科學(xué)家Tony Hoare提出的,多年后Hoare為自己的這個(gè)想法感到后悔莫及袍啡,并認(rèn)為這是"價(jià)值百萬的重大失誤"踩官。可見空指針是多么不受待見葬馋。
NullPointerException是Java開發(fā)中最常遇見的異常卖鲤,遇到這種異常我們通常的解決方法是在調(diào)用的地方加一個(gè)if判空肾扰。
if判空越多會(huì)造成過多的代碼分支畴嘶,后續(xù)代碼維護(hù)也就越來越復(fù)雜。
比如看下面這個(gè)例子集晚,使用過多的if判空窗悯。
Person對(duì)象里定義了House對(duì)象,House對(duì)象里定義了Address對(duì)象:
publicclassPerson{privateString name;privateintage;privateHouse house;publicHousegetHouse(){returnhouse;}}classHouse{privatelongprice;privateAddress address;publicAddressgetAddress(){returnaddress;}}classAddress{privateString country;privateString city;publicStringgetCity(){returncity;}}
現(xiàn)在獲取這個(gè)人買房的城市偷拔,那么通常會(huì)這樣寫:
publicStringgetCity(){String city=newPerson().getHouse().getAddress().getCity();returncity;}
但是這樣寫容易出現(xiàn)空指針的問題蒋院,比如這個(gè)人沒有房亏钩,House對(duì)象為null。接著你會(huì)改造這段代碼欺旧,加上很多判斷條件:
publicStringgetCity2(Person person){if(person!=null){House house=person.getHouse();if(house!=null){Address address=house.getAddress();if(address!=null){String city=address.getCity();returncity;}}}return"unknown";}
為了避免空指針異常姑丑,每一層都加上判斷,但是這樣會(huì)造成代碼嵌套太深辞友,不易維護(hù)栅哀。
你可能想到如何改造上面的代碼,比如加上提前判空退出:
publicStringgetCity3(Person person){String city="unknown";if(person==null){returncity;}House house=person.getHouse();if(house==null){returncity;}Address address=house.getAddress();if(address==null){returncity;}returnaddress.getCity();}
但是這樣簡單的代碼已經(jīng)加入了三個(gè)退出條件称龙,非常不利于后面代碼維護(hù)留拾。那怎樣才能將代碼寫的優(yōu)雅一點(diǎn)呢,下面引入今天的主角"Optional"鲫尊。
從Java8開始引入了一個(gè)新類 java.util.Optional痴柔,這是一個(gè)對(duì)象的容器,意味著可能包含或者沒有包含一個(gè)非空的值疫向。下面重點(diǎn)看一下Optional的常用方法:
publicfinalclassOptional<T>{// 通過指定非空值創(chuàng)建Optional對(duì)象// 如果指定的值為null咳蔚,會(huì)拋空指針異常publicstatic<T>Optional<T>of(T value){returnnewOptional<>(value);}// 通過指定可能為空的值創(chuàng)建Optional對(duì)象publicstatic<T>Optional<T>ofNullable(T value){returnvalue==null?empty():of(value);}// 返回值,不存在拋異常publicTget(){if(value==null){thrownewNoSuchElementException("No value present");}returnvalue;}// 如果值存在鸿捧,根據(jù)consumer實(shí)現(xiàn)類消費(fèi)該值publicvoidifPresent(Consumer<?superT>consumer){if(value!=null)consumer.accept(value);}// 如果值存在則返回屹篓,如果值為空則返回指定的默認(rèn)值publicTorElse(T other){returnvalue!=null?value:other;}// map flatmap等方法與Stream使用方法類似,這里不再贅述匙奴,讀者可以參考之前的Stream系列堆巧。}
以上就是Optional類常用的方法,使用起來非常簡單泼菌。
(1)創(chuàng)建Optional實(shí)例
創(chuàng)建空的Optional對(duì)象谍肤。可以通過靜態(tài)工廠方法Optional.Empty() 創(chuàng)建一個(gè)空的對(duì)象哗伯,例如:
Optional<Person>optionalPerson=Optional.Empty();
指定非空值創(chuàng)建Optional對(duì)象荒揣。
Person person=newPerson();Optional<Person>optionalPerson=Optional.of(person);
指定可能為空的值創(chuàng)建Optional對(duì)象。
Person person=null;// 可能為空Optional<Person>optionalPerson=Optional.of(person);
(2)常用方法
ifPresent
如果值存在焊刹,則調(diào)用consumer實(shí)例消費(fèi)該值系任,否則什么都不執(zhí)行。舉個(gè)栗子:
String str="hello java8";// output: hello java8Optional.ofNullable(str).ifPresent(System.out::println);String str2=null;// output: nothingOptional.ofNullable(str2).ifPresent(System.out::println);
filter, map, flatMap
在三個(gè)方法在前面講Stream的時(shí)候已經(jīng)詳細(xì)講解過虐块,讀者可以翻看之前寫的文章俩滥,這里不再贅述。
orElse
如果value為空贺奠,則返回默認(rèn)值霜旧,舉個(gè)栗子:
publicvoidtest(String city){String defaultCity=Optional.ofNullable(city).orElse("unknown");}
orElseGet
如果value為空,則調(diào)用Supplier實(shí)例返回一個(gè)默認(rèn)值儡率。舉個(gè)例子:
publicvoidtest2(String city){// 如果city為空挂据,則調(diào)用generateDefaultCity方法String defaultCity=Optional.of(city).orElseGet(this::generateDefaultCity);}privateStringgenerateDefaultCity(){return"beijing";}
orElseThrow
如果value為空以清,則拋出自定義異常。舉個(gè)栗子:
publicvoidtest3(String city){// 如果city為空崎逃,則拋出空指針異常掷倔。String defaultCity=Optional.of(city).orElseThrow(NullPointerException::new);}
再看一遍重構(gòu)之前的代碼,使用了三個(gè)if使代碼嵌套層次變得很深个绍。
// before refactorpublicStringgetCity2(Person person){if(person!=null){House house=person.getHouse();if(house!=null){Address address=house.getAddress();if(address!=null){String city=address.getCity();returncity;}}}return"unknown";}
使用Optional重構(gòu)
publicStringgetCityUsingOptional(Person person){String city=Optional.ofNullable(person).map(Person::getHouse).map(House::getAddress).map(Address::getCity).orElse("Unknown city");returncity;}
只使用了一行代碼就獲取到city值今魔,不用再去不斷的判斷是否為空,這樣寫代碼是不是很優(yōu)雅呀障贸。趕緊用Optional重構(gòu)你的項(xiàng)目吧~