Java 8 Optional详解

在进行Java开发的时候NullPointerException已经算是我们的老朋友了,有些情况没有考虑到就很有可能出现空指针异常,即使考虑到了也要使用类似 if (obj != null){ } 去判断是否为空,这样确实会让代码看上去复杂一些.现在Java8有了Optional之后,空指针的校验就变得非常的方便和简洁,可以理解为将数据作为泛型封装到Optional对象中而形成的空指针预防机制,下面我们就来看看Optional的用法.

1、基本使用

Optional使用起来并不复杂,常用的主要是以下几个方法:

// 创建一个Optional<T>对象,如果传入的value为空则抛出NullPointerException
public static <T> Optional<T> of(T value)

// 创建一个Optional<T>对象,如果传入的value为空则返回一个空的Optional对象(new Optional<>())
public static <T> Optional<T> ofNullable(T value)

// 获取Optional中的值,如果值为空则抛出NoSuchElementException
public T get()

// 判断Optional中的值是否不为空,不为空返回true,反之返回false
public boolean isPresent()

// 判断Optional中的值是否为空,不为空则返回值,为空则返回传入的值
public T orElse(T other)

// 判断Optional中的值是否为空,不为空则返回值,为空则抛出传入的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

// 传入一个Lambda表达式,返回一个对应的Optional
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

前面五个方法使用起来都非常的简单,就不一一演示了,主要演示一下最后两个方法

首先创建一个简单的User类

@Data
@AllArgsConstructor
class User {
    /**
     * 用户id
     */
    private Long id;

    /**
     * 用户名称
     */
    private String name;
}

比如现在有这样一个情况,如果User为null或者User下面的name为null都抛出一个NullPointerException,如果是传统的写法就会非常的冗余,阅读性较差

if (user == null) {
    throw new NullPointerException("user or name is null");
} else {
    if (user.getName() == null || user.getName().isEmpty()) {
        throw new NullPointerException("user or name is null");
    }
}

但是有了Optional之后一切就变得很方便简洁了,使用一行代码就可以实现,而且可读性也非常高

Optional.ofNullable(user)
        .map(temp -> temp.getName())
        .orElseThrow(() -> new NullPointerException("user or name is null"));

这段代码用上了ofNullable、map以及orElseThrow三个方法,下面通过源码我们来一一分析一下这三个方法

private static final Optional<?> EMPTY = new Optional<>();

private final T value;

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

public static<T> Optional<T> empty() {
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

这里我把需要用到的源码贴了出来,通过源码我们可以将调用的方法链分为三个步骤:

  1. ofNullable():调用ofNullable方法的时候会对传入的值进行空验证,如果不为空再调用of方法把值设置到成员变量value中去,如果为空则new一个空的Optional(这里的Optional不为null,但是里面的value为null);
  2. map():调用map方法的时候也会对value进行空验证,如果不为空则进行后面的操作(这里是返回用户的姓名Optional<String>),如果为空则同样new一个空的Optional(这里的Optional不为null,但是里面的value为null);
  3. orElseThrow():调用orElseThrow方法的时候也会对value进行空验证,如果不为空则返回对应的值,如果为空则抛出一个传入的异常.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值