欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Optional 详解

程序员文章站 2022-03-04 11:49:20
...

目录

 

Java 8 实战:用 Optional 取代 null

1、创建 Optional 对象

例子:Person、Car、Insurance

2、map  从Optional中提取、转换值

3、flatMap  链接 Optional 对象

4、读取 Optional 实例中的变量值

5、map、flatMap:以不解包的方式组合两个 Optional 对象

6、filter:剔除特定值

Optional 源码


Java 8 实战:用 Optional 取代 null

  • Optional类设计时没考虑将其作为类的字段使用,所以并未实现 Serializable接口,因此如果应用使用了某些要求序列化的库或者框架,在域模型中使用Optional,有可能引发应用程序故障

  • 可以将Optional看成最多包含一个元素的Stream对象

  • 可用返回Optional对象的方式替换包装返回null、抛异常的方法

  • 不推荐使用基础类型的Optional,因为基础类型的Optional不支持map、flatMap以及filter方法

 

1、创建 Optional 对象

Optional<T> opt=Optional.empty();           // 返回空Optional
Optional<T> opt=Optional.of(value);         // value不可为null,否则抛异常
Optional<T> opt=Optional.ofNullable(value)  // value可为null

例子:Person、Car、Insurance

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; }
}

2、map  从Optional中提取、转换值

Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);    // optInsurance非null时返回其name,否则返回不包含值的Optional<String>类型对象

3、flatMap  链接 Optional 对象

public String getCarInsuranceName(Optional<Person> person) {
  return person.flatMap(Person::getCar)       // Person -> Optional<Car>    直接返回
               .flatMap(Car::getInsurance)    // Car -> Optional<Insurance> 直接返回
               .map(Insurance::getName)       // Insurance -> String   打包为 Optional<String> 返回
               .orElse("Unknown");    // 当调用链路上任何一个方法返回空Optional时,返回默认值“Unkonwn”
}

4、读取 Optional 实例中的变量值

get();          // 不安全,值不存在时会抛异常
orElse();       // 值不存在时可提供默认值(已经创建好的默认值)
orElseGet();    // 值不存在时才创建默认值
orElseThrow();  // 值不存在时抛异常,可定制异常类型
ifPresent();    // 值存在时才执行入参提供的方法

5、map、flatMap:以不解包的方式组合两个 Optional 对象

Public Optional<Insurance> nullSafeFindCheapestInsurance(Optional<Person> person,Optional<Car> car){
  return person.flatMap(p->car.map(c->findCheapestInsurance(p,c)));
}   // person 为空时,p->() 语句不会执行,函数返回空Optional,person 非空时 p->() 语句返回 Optional<Insurance> ;
    // car 为空时 c->()返回空Optional,函数返回空Optional,car和person都非空时,函数调用findCheapestInsurance返回 Optional<Insurance>     

6、filter:剔除特定值

Optional<Insurance> optInsurance = ...;
optInsurance.filter(insurance ->"CambridgeInsurance".equals(insurance.getName()))   // filter 返回满足条件的 Optional
						.ifPresent(x -> System.out.println("ok"));

 

Optional 源码

public final class Optional<T> {  

    private static final Optional<?> EMPTY = new Optional<>();                 // 创建空 Optional 对象
    private final T value;                                                     // value==null 时表示不存在value
    private Optional() { this.value = null;}                                   // 内部调用的构造器
  	private Optional(T value) { this.value = Objects.requireNonNull(value);}   // 内部调用的构造器,value为null时抛NullPointerException

  // public
    public static<T> Optional<T> empty() {                      // 返回空Optional实例
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;    
        return t;
    }

    public static <T> Optional<T> of(T value) {                  // 返回指定value的Optional对象,value为null时抛NullPointerException异常(用非空value创建Optional)
        return new Optional<>(value);
    }

    public static <T> Optional<T> ofNullable(T value) {          // value非空时返回包含value的Optional对象,否则返回空Optional对象(允许用空值创建Optional)
        return value == null ? empty() : of(value);
    }

    public T get() {                                             // Optional中包含非空value时返回value,否则抛NoSuchElementException异常
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    public boolean isPresent() {                                 // Optional实例中存在非空value时返回true
        return value != null;
    }

    public void ifPresent(Consumer<? super T> consumer) {        // value非空时触发入参consumer指定的操作
        if (value != null)
            consumer.accept(value);
    }

    public Optional<T> filter(Predicate<? super T> predicate) {  // value不为空且符合predicate条件时,返回包含此value的Optional实例,否则返回空Optional
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;   // value为空返回空Optional本身
        else
            return predicate.test(value) ? this : empty();  
    }

  // 可用于对optional实例的后处理,无须显式检查返回值的状态
    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {  // value非空时,对其应用mapper映射,返回value映射结果的Optional实例
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));    // T->U:apply返回的U会被打包为Optional<U>,作为map的返回值
        }
    }
   
  // 类似于map,但入参mapper的返回已经是Optional类型,触发flatMap中的apply操作时,无须再将其打包为Optional
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) { // value非空时返回其映射后的值,否则返回空Optional
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value)); // T->Optional<U>:apply返回的就是Optional<U>,flatMap无须打包直接返回 
        }
    }

    public T orElse(T other) {                             // value非空时返回value,否则返回other
        return value != null ? value : other;
    }

    public T orElseGet(Supplier<? extends T> other) {      // value非空时返回value,否则返回other
        return value != null ? value : other.get();
    }
  
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {  // value非空时返回value,否则抛出入参提供的异常
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }