[Optional]优雅地使用Optionl判空

在日常开发当中,总是会碰到使用 if (obj == null) 判空的情形,假如 obj 内部还有属性要判空,属性的内部还需要判空,那么代码就可能写成这样:

```java if (obj != null) { // ... if (obj.foo != null) { // .... if (obj.foo.bar != null) { // ... } } }

```

这样就会造成大量的 if 嵌套,代码可读性大幅降低,这时候就需要考虑优化一下这样的屎山代码了。首先想到的就是使用 Optional 类,这个类是 Java 8 内置的类,专门用于判空操作,与嵌套式的 if (obj == null) 不同,Optional 是链式的。就好比 JavaScript 的 Promise 把嵌套回调函数变成了链式调用,从而避免了回调地狱,Optional 也很类似。

先来看几个 Optional 的常用 API: - static <T> Optional<T> ofNullable(T value):假如值为空则返回一个空的 Optional,否则把这个值添加到 Optional 内部。 - T orElse(T other):无值则返回 t。 - T orElseGet(Supplier<? extends T> other):无值则使用 Supplier 生成一个值返回。 - T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X:无值则使用 Supplier 生成一个异常抛出。

还有用于消费 Optional 值的 API:

  • void ifPresent(Consumer<? super T> consumer):假如值存在,那么就调用一个消费者回调函数。

管道化 Optional API:

  • <U> Optional<U> map(Function<? super T, ? extends U> mapper):如果值不为空,把 Optional 内部的值转化为另一种类型。
  • <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper):如果值不为空,将嵌套的 Optional<Optional<T>> 转化为 Optional<U>
  • Optional<T> filter(Predicate<? super T> predicate):如果值不为空,假如满足断言条件就保留否则返回一个空的 Optional。

下面来看一个具体的例子,在使用地图 API 获取出行路线的规划时,第三方服务会返回一段很长的 json 数据,需要我们来解析这段 json 数据:

如果一层接着一层解析的话,那么必须要使用 if (obj == null) 判空以避免空指针异常,那么代码就会写成上文说到的那样,十分丑陋可读性非常差。

image.png

那么来看看如何使用 Optional 优化代码:

image.png

可以从图中看到,大量使用了 map 方法,使用 map 方法目的是将一种类型转化为另一种类型,其实说白了就是相当于是隐式地做了一个非空判断,然后拿到下一层的数据继续判断。Optional 类的方法基本上都是前置条件都是值不为空,看以下 map 方法的源码就知道了它内部做了什么:

java 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 了,调用的其他的方法自然也会返回空的 Optional 直到链式调用结束。这里的 Optional 适用于 if 嵌套太多的情况,但是也不要为了使用 Optional 而使用 Optional,因为可能会产生性能问题。

猜你喜欢

转载自blog.csdn.net/weixin_45254062/article/details/129665159