我相信全部的Java程序猿必定都遇到過NullPointerException
,空指針在Java程序中是最多見的,也是最煩人的;它讓咱們不少程序猿產生了根深蒂固的感受,全部可能產生空指針的地方都的加上if-else
檢查,可是這帶給咱們不少麻煩java
if-else
的空檢查,甚至是多層嵌套,代碼可讀性降低無
前兩點不須要特別的說明,後兩點舉個例子來講明一下:
假如一我的擁有一個手機,每一個手機都有生成廠商,每一個廠商都會有個名字,用類表示的話:app
public class Person { private Phone phone; public Phone getPhone() { return phone; } } public class Phone { private Producer producer; public Producer getProducer() { return producer; } } public class Producer { private String name; public String getName() { return name; } }
在這個例子中,假如咱們須要取到手機生成廠商的名字ide
public String getPhoneProducerName(Person person) { return person.getPhone().getProducer().getName(); }
因爲不必定每一個人都會有一個手機,全部在調用getProducer()
時可能會出現NullPointerException
。函數
一門設計語言原本就是來描述世界的,在這個事例中有的人有手機,有的人也可能沒有手機,因此在調用person.getPhone()
返回的值就應該包含有和無這兩種狀況,如今經過返回null
來表示無,可是在調用getProducer()
卻又會拋出異常,這樣就不太符合現實邏輯;因此把null
來用來表示無
不合適學習
在遇到這種狀況一般的作法是作null檢查,甚至是每一個地方可能發生null指針的作檢查。ui
public String getPhoneProducerName(Person person) { if (person.getPhone() == null) { return "無名字"; } if (person.getPhone().getProducer() == null) { return "無名字"; } return person.getPhone().getProducer().getName(); }
這裏我已經試圖在減小代碼的層級,若是使用的是if-else
,代碼的層級會更深,代碼可讀性降低。設計
吐槽了那麼多現狀的很差,如今能夠祭出咱們的解決方案了 Optional
;千呼萬喚始出來,猶抱琵琶半遮面;那Optional
究竟是個什麼東西,咱們一塊兒來逐步解開它的面紗。指針
Optional
自己只是對對象的簡單包裝,若是對象爲空,那麼會構建一個空的Optional
;這樣一來Optional
就包含了存在和不存在兩個狀況, 接下來能夠看下上面的例子改過以後code
public class Person { private Optional<Phone> phone; public Optional<Phone> getPhone() { return phone; } } public class Phone { private Producer producer; public Producer getProducer() { return producer; } } public class Producer { private String name; public String getName() { return name; } }
因爲有的人可能沒有手機,有的人有,因此Phone
須要用Optional
包裝起來;手機自己必定會有生產的廠商,廠商必定會有一個名字,因此這兩個不須要用Optional
包裝起來。這裏咱們會發現使用了Optional
會豐富代碼的語義,讓代碼更加符合現實。對象
而當咱們在調用phone.getProducer().getName()
的時候不須要作null指針的檢查,若是說在這裏發生了NullPointerException
,說明這裏數據自己是有問題的,不符合現實,就應該讓問題暴露出來,而不是像上面的代碼同樣把問題掩蓋。
Optional<Person> empty = Optional.empty(); //申明一個空的Optional Optional<Person> person = Optional.of(new Person()); //包裝Person Optional<Person> person2 = Optional.of(null); //不容許的操做,傳入null 會拋出空指針異常 Optional<Person> optionalPerson = Optional.ofNullable(null); //容許傳null, 返回一個空的Optional
public class Phone { private String model; private Producer producer; public Producer getProducer() { return producer; } public String getModel() { return model; } }
當咱們須要獲取到手機的型號的時候能夠這樣:
Optional<Phone> optionalPhone = Optional.of(new Phone()); Optional<String> model = optionalPhone.map(Phone::getModel);
當咱們須要經過Person對象獲取到Phone的型號是,會想到這樣:
Optional<Person> optionalPerson = Optional.of(new Person()); optionalPerson.map(Person::getPhone).map(Phone::getModel);
當咱們寫出來的時候發現編譯器不能經過。是由於Person::getPhone
返回的是一個Optional<Phone>
,調用optionalPerson.map(Person::getPhone)
返回的就是Optional<Optional<Phone>>
,因此再.map
的就沒法拿到手機型號,那如何可以讓返回的結果不是Optional<Optional<Phone>>
,而是Optional<Phone>
呢?
這裏須要用到另外一個方法flatMap
。flatMap
和map
的區別,我在剛開始學習的時候,看到了網上的各類解釋都很繞,看的很暈,最後直接打開源碼來看,發現實現很簡單,很容易理解,來看下源碼:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } } public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Objects.requireNonNull(mapper.apply(value)); } }
map
方法在返回的時候會包裝一層Optional
; flatMap
在返回的時候直接把函數的返回值返回了,函數的結果必須是Optional
;那麼在前面的例子中咱們直接調用flatMap
返回的結果就是Optional<Phone>
Optional<Person> optionalPerson = Optional.of(new Person()); optionalPerson.flatMap(Person::getPhone).map(Phone::getModel);
取出Optional
中的值對象:get、orElse、orElseGet、orElseThrow、ifPresent
NoSuchElementException
;因此當若是存在空值的話建議就不要調用該方法,由於這樣和作null檢查就沒有區別了consumer
函數,若是值爲空,那麼這個方法什麼都不作IOS
的手機,並打印出型號,代碼以下:Person person = new Person(Optional.of(new Phone("IOS"))); Optional<Person> optionalPerson = Optional.of(person); optionalPerson.flatMap(Person::getPhone) .filter(phone -> "IOS".equals(phone.getModel())) .map(Phone::getModel) .ifPresent(System.out::println);
Optional
來表示有和無的狀況以及初始化的方式Optional
中常用到的方法本人菜鳥,若是有任何寫的不對的地方,歡迎在評論區指出
原創不易 轉載請註明出處:https://silently9527.cn/archives/56