背景
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();
}
若person.getCar()或者person.getCar().getInsurance()为空,那么会抛出空指针引用。为避免这种隐患,我们可能会采用防御式编程,层层嵌套if语句进行判断。现在我们可以不必这样做,因为java8引入了一个新的类Optional,用来代替null。
使用
-
创建Optional对象的三种方式:
- 声明一个空的Optional
Optional<Car> optCar = Optional.empty();
- 依据一个非空值创建Optional
Optional<Car> optCar = Optional.of(car);
- 可接受null的Optional
Optional<Car> optCar = Optional.ofNullable(car);
// 每次你希望安全地对潜在为null的对象进行转换,将其替换为Optional对象时,都可以考 虑使用这种方法
-
从Optional中获取值的方式
例:从Insurance中获取name
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
上述代码得到一个Optional<String>对象,那么如何获取最终的String值,java8提供了如下几种方式:
- Optional.get()
最简单但又最不安全的方法。如果变量存在,它直接返回封装的变量 值,否则就抛出一个NoSuchElementException异常。
- Optional.orElseGet(Supplier<? extends T> other)
是orElse方法的延迟调用版,Supplier 方法只有在Optional对象不含值时才执行调用
- Optional.orElseThrow(Supplier<? extends X> exceptionSupplier)
和get方法非常类似, 它们遭遇Optional对象为空时都会抛出一个定制的异常
- Optional.orElse(T other)
允许你在 Optional对象不包含值时提供一个默认值。
- Optional.ifPresent(Consumer<? super T>)
让你能在变量值存在时执行一个作为参数传入的 方法,否则就不进行任何操作
-
使用flatMap连接Optional对象
获取最终的name
Optional<Person> optPerson = Optional.of(person); optPerson.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown");