Java8特性中的Optional可以用来优雅的判空,Optional来自官方的介绍如下:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

一个可能包含也可能不包含非null值的容器对象。 如果存在值,isPresent()将返回trueget()将返回该值。

如下代码,需要获得Test2中的Info信息,但是参数为Test4,我们要一层层的申请,每一层都获得的对象都可能是空,最后的代码看起来就像这样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public String testSimple(Test4 test) {
if (test == null) {
return "";
}
if (test.getTest3() == null) {
return "";
}
if (test.getTest3().getTest2() == null) {
return "";
}
if (test.getTest3().getTest2().getInfo() == null) {
return "";
}
return test.getTest3().getTest2().getInfo();
}

使用Optional

1
2
3
4
5
6
public String testOptional(Test test) {
return Optional.ofNullable(test).flatMap(Test::getTest3)
.flatMap(Test3::getTest2)
.map(Test2::getInfo)
.orElse("");
}

1、Optional.ofNullable(test),如果test为空,则返回一个单例空Optional对象,如果非空则返回一个Optional包装对象,Optionaltest包装;

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

2、flatMap(Test::getTest3)判断test是否为空,如果为空,继续返回第一步中的单例Optional对象,否则调用TestgetTest3方法;

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

3、flatMap(Test3::getTest2)同上调用Test3getTest2方法;

4、map(Test2::getInfo)flatMap类似,但是flatMap要求Test3::getTest2返回值为Optional类型,而map不需要,flatMap不会多层包装,map返回会再次包装Optional

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));
}
}

5、orElse("");获得map中的value,不为空则直接返回value,为空则返回传入的参数作为默认值。

1
2
3
public T orElse(T other) {
return value != null ? value : other;
}

使用Optional后的代码是不是瞬间变得非常整洁,或许看到这段代码你会有很多疑问,针对复杂的一长串判空,Optional有它的优势,但是对于简单的判空使用Optional也会增加代码的阅读成本、编码量以及团队新成员的学习成本。毕竟Optional在现在还并没有那样流行,它还拥有一定的局限性。


文章内容来源