Optional 练习、实战

Optional 练习、实战

薛定谔的汪

前言

Optional 类位于 java.util 包下,是 Java8 新增的类,使用它并结合 Lambda 表达式可以帮住我们进行优雅的判空,接下来通过实战来深入地学习它吧。

Optional

使用静态方法构造 Optional

Optional.of(T value)

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

通过源码可知通过该方法构造的 Optional 要求目标对象不能为 null,否则抛出 NPE,一般用于确定目标对象不为空,或者强制要求目标对象不能为 null,如果为 null,则任务抛出异常并终止程序的情况。第二种情况有点类似于断言。

Optional.ofNullable(T value)

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

该构造方法可以接受一个为 null 的目标对象,如果目标对象为 null ,则默认一个 empty 的 Optional 对象

1
2
3
4
5
6
private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}

常用的 API

ifPresent 方法

场景:当我们远程调用一个服务的时候,因为不确定对方返回的结果是否为 null(毕竟是不信任编程),通常会这样写:

1
2
3
4
Person person = personFeginClient.queryById(id);
if (person != null) {
// doSomething...
}

但是有了 Optional 后你可以:

1
2
3
4
5
Person person = personFeginClient.queryById(id);
Optional.ofNullable(person) //
.ifPresent(p -> {
// doSomething...
});

因为不确定 person 是否为 null, 所以用 Optional.ofNullable方法接受 person,ifPresent方法表示,只有当目标对象不为 null 的时候才执行该方法体的内容,如果执行的方法代码很多,你可以抽取出来,比如这样:

1
2
3
4
5
6
7
Person person = personService.queryById(id);
Optional.ofNullable(person)
.ifPresent(this::doSomething);

private void doSomething(Person person) {
// doSomething...
}

orElse 方法

orElse 方法可以指定当目标对象不为 null 时,返回该目标对象,为 null 时,返回一个默认对象:

以前这样写:

1
2
3
4
Person person = personService.queryById(id);
if (person == null) {
person = DEFAULT_PERSON
}

现在可以这样写:

1
person = Optional.ofNullable(person).orElse(DEFAULT_PERSON);

orElseGet 方法

orElseGetorElse 方法的区别在于,orElseGet 方法传入的参数为一个 Supplier接口的实现 ,当目标对象不为 null 时,返回该目标对象,为 null 时返回从 Supplier 获得的值,我们可以在该 Supplier 中执行获取默认对象的逻辑:

1
2
3
4
Optional.ofNullable(person).orElseGet(this::getDefault);
private Person getDefault() {
return new Person();
}

orElseThrow 方法

orElseThrow 方法和 orElse 方法区别是当目标对象为 null 时,可以抛出一个异常:

1
Optional.ofNullable(person).orElseThrow(RuntimeException::new);

map

1
2
3
4
5
6
7
8
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));
}
}

Optional 的 map 方法和 Stream 的 map 方法类似,都是改变原目标对象并返回新对象的操作,而且,map 可以进行多次操作:

1
2
3
4
5
Person person = personService.queryById(id);
Optional<String> s = Optional.ofNullable(person)
.map(Person::getName)
.map(String::toLowerCase)
.map(name -> name.replace("-", ""));

filter 方法

和 Stream 的 filter 方法一样,Optional 也可以用此方法来过滤元素:

1
2
3
4
5
6
7
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
1
2
3
4
5
Person person = personService.queryById(id);
Integer score = Optional.ofNullable(person)
.filter(p -> p.getName().startsWith("Z"))
.map(Person::getScore)
.orElse(null);

总结

使用 Optional,可以帮助我们更优雅地处理 null,不必像以前那样繁琐地 if(obje == null){...},同时它丰富的 API 也使我们的程序代码更简洁,可读性更好(当然是在熟悉其 api 的情况下;

  • Title: Optional 练习、实战
  • Author: 薛定谔的汪
  • Created at : 2019-01-15 18:01:54
  • Updated at : 2023-11-17 19:37:37
  • Link: https://www.zhengyk.cn/2019/01/15/java/Optional-practice/
  • License: This work is licensed under CC BY-NC-SA 4.0.