怎樣作才能避免不期而至的NullPointerException呢?一般,能夠在須要的地方添加null的檢查(過於激進的防護式檢查甚至會在不太須要的地方添加檢測代碼),而且添加的方式每每各有不一樣。java
「深層質疑」,緣由是它不斷重複着一種模式:每次不肯定一個變量是否爲null時,都須要添加一個進一步嵌套的if塊,也增長了代碼縮進的層數。很明顯,這種方式不具有擴展性,同時還犧牲了代碼的可讀性。安全
第二種嘗試中,試圖避免深層遞歸的if語句塊,採用了一種不一樣的策略:每次遭遇null變量,都返回一個字符串常量「Unknown」。然而,這種方案遠非理想,如今這個方法有了四個大相徑庭的退出點,使得代碼的維護異常艱難。spa
汲取Haskell和Scala的靈感,Java 8中引入了一個新的類java.util.Optional<T>。這是一個封裝Optional值的類。設計
public String getCarInsuranceName(Optional<Person> person){ return person.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown");//若是Optional的結果值爲空,設置默認值 }
1. 聲明一個空的Optional指針
能夠經過靜態工廠方法Optional.empty,建立一個空的Optional對象:code
Optional<Car> optCar = Optional.empty();
2. 依據一個非空值建立Optional對象
還可使用靜態工廠方法Optional.of,依據一個非空值建立一個Optional對象:blog
若是car是一個null,這段代碼會當即拋出一個NullPointerException,而不是等到試圖訪問car的屬性值時才返回一個錯誤。遞歸
Optional<Car> optCar = Optional.of(car);
3. 可接受null的Optiona字符串
使用靜態工廠方法Optional.ofNullable,能夠建立一個容許null值的Optional對象:
若是car是null,那麼獲得的Optional對象就是個空對象。
Optional<Car> optCar = Optional.ofNullable(car);
Optional類的方法
•null引用在歷史上被引入到程序設計語言中,目的是爲了表示變量值的缺失。
•Java 8中引入了一個新的類java.util.Optional<T>,對存在或缺失的變量值進行建模。
•可使用靜態工廠方法Optional.empty、Optional.of以及Optional.ofNullable建立Optional對象。
•Optional類支持多種方法,好比map、flatMap、filter,它們在概念上與Stream類中對應的方法十分類似。
•使用Optional會迫使更積極地解引用Optional對象,以應對變量值缺失的問題,最終,能更有效地防止代碼中出現不期而至的空指針異常。
•使用Optional能幫助設計更好的API,用戶只須要閱讀方法簽名,就能瞭解該方法是否接受一個Optional類型的值。
附:類代碼
public class Person { private Car car; public Car getCar() { return car; } } public class Car { private Insurance insurance; public Insurance getInsurance() { return insurance; } } public class Insurance { private String name; public String getName() { return name; } }
附:使用Optional從新定義Person/Car/Insurance的數據模型
public class Person { private Optional<Car> car;//人可能有車,也可能沒有車,所以將這個字段聲明爲Optional public Optional<Car> getCar() { return car; } } public class Car { private Optional<Insurance> insurance;//車可能進行了保險,也可能沒有保險,因此將這個字段聲明爲Optional public Optional<Insurance> getInsurance() { return insurance; } } public class Insurance { private String name;//保險公司必須有名字 public String getName() { return name; } }
文章來源:java8實戰 第十章