前言
建構Person/Car/Insurance的資料模型
//人
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; }
}
取值
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
java.lang.NullPointerException異常
null值檢查
//1.深度質疑
public String getCarInsuranceName(Person person) {
if (person != null) {
Car car = person.getCar();
if (car != null) {
Insurance insurance = car.getInsurance();
if (insurance != null) {
return insurance.getName();
}
}
}
return "Unknown";
}
//2.退出語句
public String getCarInsuranceName(Person person) {
if (person == null) {
return "Unknown";
}
Car car = person.getCar();
if (car == null) {
return "Unknown";
}
Insurance insurance = car.getInsurance();
if (insurance == null) {
return "Unknown";
}
return insurance.getName();
}
Optional
Optional是對值的簡單封裝,說明值要麼存在,要麼不存在。
建立Optional對象
- 聲明一個空的Optional
Optional<Car> optCar = Optional.empty();
- 依據一個非空值建立Optional
Optional<Car> optCar = Optional.of(car);
- 可接受null的Optional
Optional<Car> optCar = Optional.ofNullable(car);
使用map從Optional對象中提取和轉換值
String name = null;
if(insurance != null){
name = insurance.getName();
}
//優化後
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
使用flatMap連結Optional對象
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
應對剛開始的資料模型
Optional<Person> optPerson = Optional.of(person);
Optional<String> name =
optPerson.map(Person::getCar)
.map(Car::getInsurance)
.map(Insurance::getName);
重新設計資料模型
public class Person {
private Optional<Car> car;
public Optional<Car> getCar() { return car; }
}
public class Car {
private Optional<Insurance> insurance;
public Optional<Insurance> getInsurance() { return insurance; }
}
public class Insurance {
private String name;
public String getName() { return name; }
}
取值
Optional<Person> optPerson = Optional.of(person);
Optional<String> name =
optPerson.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknown");
預設行為及解引用 Optional 對象
采用orElse方法讀取這個變量的值,使用這種方式你還可以定義一個預設值,遭 遇空的Optional變量時,預設值會作為該方法的調用傳回值。 Optional類提供了多種方法讀取 Optional執行個體中的變量值
- get()是這些方法中最簡單但又最不安全的方法。如果變量存在,它直接傳回封裝的變量 值,否則就抛出一個NoSuchElementException異常。是以,除非你非常确定Optional 變量一定包含值,否則使用這個方法是個相當糟糕的主意。此外,這種方式即便相對于 嵌套式的null檢查,也并未展現出多大的改進。
- orElse(T other)是我們在代碼清單10-5中使用的方法,正如之前提到的,它允許你在 Optional對象不包含值時提供一個預設值。
- orElseGet(Supplier<? extends T> other)是orElse方法的延遲調用版, Supplier 方法隻有在Optional對象不含值時才執行調用。如果建立預設值是件耗時費力的工作, 你應該考慮采用這種方式(借此提升程式的性能),或者你需要非常确定某個方法僅在 Optional為空時才進行調用,也可以考慮該方式(這種情況有嚴格的限制條件)。
- orElseThrow(Supplier<? extends X> exceptionSupplier)和get方法非常類似, 它們遭遇Optional對象為空時都會抛出一個異常,但是使用orElseThrow你可以定制希 望抛出的異常類型。
- ifPresent(Consumer<? super T>)讓你能在變量值存在時執行一個作為參數傳入的 方法,否則就不進行任何操作。
Optional提供的方法
