Java8新特性Optional 详解

一、概述
java.util.Optional<T>类是一个封装了Optional值的容器对象,Optional值可以为null,如果值存在,调用isPresent()方法返回true,调用get()方法可以获取值。

Optional是在java.util包下的一个用于代替null的一个工具类。

Optional 类的引入很好的解决空指针异常。

import java.util.Optional;

二、使用目的
1.避免使用null检查。
开发中,几乎都会遇到NullPointerException异常,大都是通过if判定null值,比如:

public void addUserRole(User user) {
    if (user == null) {
        return;
    }
    String roleId = user.getRoleId();
    if (roleId == null) {
        return;
    }
}

这种方式不方便出错后调试,因此,Java 8中引入了一个新的类Optional,用以避免使用null值引发的种种问题。

三、构建Optional
Optional类提供类三个方法用于实例化一个Optional对象,它们分别为empty()、of()、ofNullable()。
(1)empty()方法:empty()方法用于创建一个没有值的Optional对象:

Optional<String> emptyOpt = Optional.empty();

(2)of()方法:of()方法使用一个非空的值创建Optional对象。

String str = "my";
Optional<String> notNullOpt = Optional.of(str);

(3)ofNullable()方法:ofNullable()方法接收一个可以为null的值。

Optional<String> nullableOpt = Optional.ofNullable(str);

如果str的值为null,得到的nullableOpt是一个没有值的Optional对象。

四、Optional中相关方法
1.isPresent(): 持有非空值,返回true;否则false;

Optional optional = Optional.ofNullable(null);
        Optional optional1 = Optional.of("");
        Optional optional2 = Optional.empty();
        System.out.println(optional.isPresent());
        System.out.println(optional1.isPresent());
        System.out.println(optional2.isPresent());

结果:
分别为 false、true、false。
2.ifPresent(): 如果 Optional 中有值,则对该值调用consumer.accept,否则什么也不做。
3.orElse: 参数是一个值,如果 Optional 中有值则将其返回,否则返回 orElse 方法传入的参数。
Optional 中有值:

Optional optional = Optional.ofNullable("admin");
System.out.println(optional.orElse("error"));

结果:
admin

Optional 中没有值:

//Optional 中有没有值
Optional optional = Optional.ofNullable(null);
System.out.println(optional.orElse("error"));

结果:
error
注:Optional 只有null时表示为空值,其他任何情况都不表示空值,如空字符串。

4.orElseGet: 传入的参数为一个 Supplier 接口的实现。
5.orElseThrow: 没有值的时候会抛出异常,抛出的异常由传入的 exceptionSupplier 提供。
如下:

return Optional.ofNullable(user.getUserId())
        .orElseThrow(() -> new BizException(“异常”));

6.map: 为空返回 Optional.empty;否则返回一个新的 Optional:函数 mapper 在以 value 作为输入时的输出值;可以多次使用map操作。

Optional<String> nickname = Optional.ofNullable(user.getUserId())
		.map(user -> user.getNickname())
		.map(name -> name.replace(' ', ''));
			
System.out.println("nickname is: " + nickname.orElse("unknown"));

7.flatMap: map 方法参数中的函数 mapper 输出的是值,然后 map 方法会使用 Optional.ofNullable 将其包装为 Optional;而 flatMap 要求参数中的函数 mapper 输出的就是 Optional。

Optional<String> nickname = Optional.ofNullable(user.getUserId())
		.flatMap(user -> Optional.of(user.getNickname()))
		.flatMap(name -> Optional.of(name.toLowerCase()));
		
System.out.println("nickname is: " + nickname.orElse("unknown"));

8.filter: 接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。

Optional<User> optional = Optional.ofNullable(user).filter(u -> u.getUserId == userId).orElse(null);