背景
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; }
}
針對(duì)上述定義,下列代碼有何隱患?
public String getCarInsuranceName(Person person) {
return person.getCar().getInsurance().getName();
}
若person.getCar()或者person.getCar().getInsurance()為空,那么會(huì)拋出空指針引用。為避免這種隱患,我們可能會(huì)采用防御式編程,層層嵌套if語(yǔ)句進(jìn)行判斷?,F(xiàn)在我們可以不必這樣做,因?yàn)閖ava8引入了一個(gè)新的類Optional,用來代替null。
使用
-
創(chuàng)建Optional對(duì)象的三種方式:
- 聲明一個(gè)空的Optional
Optional<Car> optCar = Optional.empty();
- 依據(jù)一個(gè)非空值創(chuàng)建Optional
Optional<Car> optCar = Optional.of(car);
- 可接受null的Optional
Optional<Car> optCar = Optional.ofNullable(car);
// 每次你希望安全地對(duì)潛在為null的對(duì)象進(jìn)行轉(zhuǎn)換,將其替換為Optional對(duì)象時(shí),都可以考 慮使用這種方法
-
從Optional中獲取值的方式
例:從Insurance中獲取name
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
上述代碼得到一個(gè)Optional<String>對(duì)象,那么如何獲取最終的String值,java8提供了如下幾種方式:
- Optional.get()
最簡(jiǎn)單但又最不安全的方法。如果變量存在,它直接返回封裝的變量 值,否則就拋出一個(gè)NoSuchElementException異常。
- Optional.orElseGet(Supplier<? extends T> other)
是orElse方法的延遲調(diào)用版,Supplier 方法只有在Optional對(duì)象不含值時(shí)才執(zhí)行調(diào)用
- Optional.orElseThrow(Supplier<? extends X> exceptionSupplier)
和get方法非常類似, 它們?cè)庥鯫ptional對(duì)象為空時(shí)都會(huì)拋出一個(gè)定制的異常
- Optional.orElse(T other)
允許你在 Optional對(duì)象不包含值時(shí)提供一個(gè)默認(rèn)值。
- Optional.ifPresent(Consumer<? super T>)
讓你能在變量值存在時(shí)執(zhí)行一個(gè)作為參數(shù)傳入的 方法,否則就不進(jìn)行任何操作
-
使用flatMap連接Optional對(duì)象
獲取最終的name
Optional<Person> optPerson = Optional.of(person); optPerson.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown");