Java 8新特性之Optional取代null(2)

  从对象中读取信息是一种比较常见的模式。比如,你可以从insurance公司对象中提取公司的名称。提取名称之前你需要检查insurance对象是否为null,如:

String name = null;
if(insurance != null){
    name = insurance.getName();   
}

为了支持这种模式,Optional提供了一个map方法。

Optional<Insurance> optionalInsurance = Optional.ofNullable(insurance);
Optional<String> name = optionalInsurance.map(Insurance::getName);

这里的map和流中的map相差无几。map操作会将提供的函数应用于流的每个元素。你可以把Optional对象看成一种特殊的集合数据。如图:

这看齐来挺有用,但是如何应用起来,重构之前的代码呢?
p.getCar().getInsurance().getName();

使用flatMap链接Optional对象

  使用刚刚的学习的map,第一反应是重写之前的代码,比如这样:

Optional<Person> person = Optional.of(p);
        Optional<String> name = person
                .map(Person::getCar)
                .map(Car::getInsurance)
                .map(Insurance::getName);

但是这段代码无法通过编译,person是Optional<Person>类型的变量,调用map方法没有问题,但是getCar返回的是一个Optional<Car>类型的对象,这意味着map操作的结果的结果是一个Optional<Optinoal<Car>>类型的对象。 因此它调用getInsurance是非法的。

在流中使用flatMap可以扁平化合并流,在这里你想把两层的Optional合并为一个。

public String getCarInsuranceName(Person p) {
        Optional<Person> person = Optional.of(p);
        return person
                .flatMap(Person::getCar)
                .flatMap(Car::getInsurance)
                .map(Insurance::getName)
                .orElse("Unknown");
    }

  通过代码的比较,处理潜在可能缺失的值时,使用Optional具有明显的优势。你可以非常容易实现期望的效果,不需要写那么多的条件分支,也不会增加代码的复杂性。

Java 8新特性之Optional取代null

首先,Optional.of(p) 生成Optional<person>对象,然后调用person.flatMap(Person::GetCar)返回一个Optional<Car> 对象,Optional内的Person也被转换成了这种对象,结果就是两层的Optional对象,最终他们会被flatMap操作合并起来。如果合并时其中有一个为空,那么就构成一个空的Optional对象。如果给一个空的Optional对象调用flatMap返回的也是空的Optional对象。

然后,flatMap(Car::getInsurance) 会转换成Optional<Insurance> 合并。 第三步 这里调用的是map方法,因为返回类型是string 就不需要flatMap了。如果连上的任何一个结果为空就返回空,否则返回的值就是期望的值。 所以最后用了一个orElse的方法,当Optional为空的时候返回一个默认值。

获取Optional对象的值:

  1. get() 是这些方法中最简单但最不安全的方法。如果变量存在,直接返回封装的变量值。否则抛出一个NoSuchElementException异常。

  2. orElse(T other) 默认值,当值存在返回值,否则返回此默认值。

  3. orElseGet(Supplier<? extends T> other) 是orElse方法的延迟调用版,Supplier方法只有在Optional对象不含值时才执行调用。

  4. orElseThrow(Supplier<? extends X> exceptionSupplier )和get方法相似,遇到Optional对象为空时都抛出一个异常,使用orElseThrow可以自定义异常类型。

  5. ifPresent(Consumer<? super T>) 在变量值存在时执行,否则什么都不做。

判断Optional是否有值 isPresent()

假设有一个方法,接受两个参数 Person 和Car 来查询便宜的保险公司:

public Insurance getInsurance(Person person ,Car car){
        //业务逻辑
        return new Insurance();
    }

这是以前的版本,使用我们今天所学的知识 可以做一个安全版本,它接受两个Optional对象作为参数 返回值也是一个Optional<Insurance>方法:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/45f2a80f5167657b9aabc74f53c43b42.html