Optional详解
- empty : 创建一个值为null的Optional对象。一般很少用。
- of : 创建一个非空值的Optional对象。值一定非空,否则将抛出NullPointerException异常。
- ofNullable : 创建一个可能为空值的Optional对象。
Optional<String> empty = Optional.empty(); // Optional.empty Optional<String> name = Optional.of("孙悟空"); // Optional[孙悟空]
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional<String> result = Optional.ofNullable(arr[index]);
String maybe = person.map(p -> "原来真的" + p).orElse("空的"); // 如果person不为空,返回"原来真的非空",否则返回"空的"
二、判断Optional中的值是否为空
Optional类提供了一个isPresent()方法来判断值是否非空,如果非空返回true,否则返回false。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2);
Optional<String> person = Optional.ofNullable(arr[index]); if (person.isPresent()) { System.out.println(person.get()); // 如果值非空就返回被包装的非空值 } else { System.out.println(Optional.empty()); // 如果值为null,则返回EMPTY }
isPresent还有一个重载方法isPresent(Consumer<? super T> consumer),其中Consumer是一个函数式接口,可以通过函数式接口给方法传递行为,这是Java 8 最牛的两个特性之一(另一个是Stream)。
该方法的作用是Optional中的值非空,就执行isPresent方法,否则就不执行。如果执行了isPresent方法,至于在isPresent方法中要干什么事,则是借助Consumer函数式接口来传递。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2);
Optional.ofNullable(arr[index])
.ifPresent(x -> System.out.println("原来真的" + x)); // 如果arr[index]非空,就输出"原来真的非空"
三、读取Optional中的值
Optional类提供了一个get方法用来读取被包装的值,当值非空时,获取该值,否则抛出NoSuchElementException异常。这个方法必须要结合isPresent()一起用,先判断再取值。但是如果是这样,那我们压根就不需要使用Optional对值进行包装,直接用if对值进行判空,更简洁明了。所以这个方法用的不多。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2);
Optional<String> optional = Optional.ofNullable(arr[index]); if (optional.isPresent()) { String s = optional.get(); }
四、操作Optional中的值
Optional中提供了map和flatMap方法对Optional中的value进行操作,然后返回包装新值的Optional对象。
- map : 如果Optional中的value非空,对value操作之后返回新值的Optional对象。如果value为空,则返回Optional的空对象。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2); Optional<String> optional = Optional.ofNullable(arr[index]); Optional<String> s = optional.map(e -> "原来真的" + e);
- flatMap : 如果Optional中的value非空,对value操作之后返回新值的Optional对象,但是新值的Optional对象需要开发者手动封装。如果value为空,则返回Optional的空对象。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2); Optional<String> optional = Optional.ofNullable(arr[index]); Optional<String> s = optional.flatMap(e -> Optional.of("原来真的" + e));
为什么会有这种区别,查看源码可以看到,map函数的返回值是Optional.ofNullable(mapper.apply(value)),已经被Optional封装了。而flatMap函数的返回值是Objects.requireNonNull(mapper.apply(value)),它没有被Optional封装,然而flatMap要求返回值是Optional<U>,所以只能手动封装。
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<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Objects.requireNonNull(mapper.apply(value)); } }
flatMap这种设计在多个Optional的链式调用时会用到。
五、Optional中的值为null怎么办
Optional提供了三个方法:orElse、orElseGet 和 orElseThrow,这三个方法都是如果有非空值,就获取值,否则做对应的处理,具体如下:
- orElse:当Optional中的值为空时,给Optional设置一个默认值。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2); Optional<String> optional = Optional.ofNullable(arr[index]); String s = optional.orElse(""); // 要么是 "非空",要么是 ""
注意到如果optional非空时,并没有通过get取获取其中的值,orElse方法也可以获取。可以查看如下源码可知,如果value非空,返回value,否则返回other。
public T orElse(T other) { return value != null ? value : other; }
- orElseGet:当Optional中的值为空时,执行Supplier行为,通过这个行为给value设置默认值。这个方法存在是因为,有时候默认值无法简单给出,而是需要通过一系列的逻辑之后才能获得,这时候orElse方法就无法满足,只能使用这个方法。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2); Optional<String> optional = Optional.ofNullable(arr[index]);
String s = optional.orElseGet(() -> {
System.out.println("一系列逻辑");
return "一系列逻辑之后获取的新值";
});
- orElseThrow:当Optional中的值为空时,抛出一个异常。
String[] arr = {null, "非空"}; int index = new Random().nextInt(2); Optional<String> optional = Optional.ofNullable(arr[index]); String s = optional.orElseThrow(() -> new RuntimeException("没有值啊"));
六、过滤Optional对象
通常我们说过滤都是针对一个列表,然而这里却是针对一个Optional对象,满足条件原样返回,不满足条件返回EMPTY
Optional中提供一个 filter 方法来决定是否返回这个Optional对象,该方法接收函数式接口断言Predicate为入参,如果断言为真且value非空,则返回value非空的Optional对象,否则返回EMPTY;
Integer[] arr = {null, 10, 100};
int index = new Random().nextInt(3);
Optional<Integer> optional = Optional.ofNullable(arr[index]);
Optional<Integer> integer = optional.filter(t -> t > 50); // 当arr[index]为null和10时,都是返回EMPTY
以上是Optional类的全部功能。