Optional 详解

目录

 

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

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值