原来 Optional 用起来这么清爽!
前言
大家好,我是捡田螺的小男孩。
最近在项目中,看到一段很优雅的代码,用 Optional 来判空的。我贴出来给大家看看:
//遍历打印 userInfoList
for (UserInfo userInfo : Optional.ofNullable(userInfoList)
.orElse(new ArrayList<>())) {
//print userInfo
}
这段代码因为 Optional 的存在,优雅了很多,因为 userInfoList
可能为 null,我们通常的做法,是先判断不为空,再遍历:
if (!CollectionUtils.isEmpty(userInfoList)) {
for (UserInfo userInfo:userInfoList) {
//print userInfo
}
}
显然,Optional 让我们的判空更加优雅啦、
- 技术大厂,前后端测试捞人,欢迎来共事
1. 没有 Optional,传统的判空?
如果只有上面这一个例子的话,大家会不会觉得有点意犹未尽呀。那行,田螺哥再来一个。
假设有一个订单信息类,它有个地址属性。
要获取订单地址的城市,会有这样的代码:
String city = orderInfo.getAddress().getCity();
这块代码会有啥问题呢?是的,可能报空指针问题!为了解决空指针问题,一般我们可以这样处理:
if (orderInfo != null) {
Address address = orderInfo.getAddress();
if (address != null) {
String city = address.getCity();
}
}
这种写法显然有点丑陋。为了更加优雅一点,我们可以使用 Optional
String city = Optional.ofNullable(orderInfo)
.map(Order::getAddress)
.map(Address::getCity)
.orElseThrow(() ->
new IllegalStateException("OrderInfo or Address is null"));
这样是不是优雅一点,好了这例子也介绍完了。
有些伙伴,可能第一眼看那个 Optional
优化后的代码有点生疏。因此,接下来,给介绍 Optional
相关 API
。
2. Optional API 简介
2.1 ofNullable(T value)、empty()、of(T value)
因为我们上面的例子,使用到了 Optional.ofNullable(T value)
,第一个函数就讲它啦。源码如下:
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
如果 value
为 null,就返回 empty()
,否则返回 of(value)
函数。接下来,我们看 Optional 的 empty()
和 of(value)
函数
public final class Optional<T> {
private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
显然, empty()
函数的作用就是返回 EMPTY
对象。
而 of(value)
函数会返回 Optional 的构造函数
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
对于 Optional 的构造函数:
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
- 当 value 值为空时,会报
NullPointerException
。 - 当 value 值不为空时,能正常构造
Optional
对象。
2.2 orElseThrow(Supplier<? extends X> exceptionSupplier)、orElse(T other) 、orElseGet(Supplier<? extends T> other)
上面的例子,我们用到了 orElseThrow
.orElseThrow(() -> new IllegalStateException("OrderInfo or Address is null"));
那我们先来介绍一下它吧:
public final class Optional<T> {
private final T value;
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
很简单就是,如果 value
不为 null
,就返回 value
,否则,抛出函数式 exceptionSupplier
的异常。
一般情况,跟 orElseThrow
函数功能相似的还有 orElse(T other)
和 orElseGet(Supplier<? extends T> other)
public T orElse(T other) {
return value != null ? value : other;
}
对于 orElse
,如果 value
不为 null
,就返回 value
,否则返回 other
。
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
对于 orElseGet
,如果 value
不为 null
,就返回 value
,否则返回执行函数式 other
后的结果。
2.3 map 和 flatMap
我们上面的例子,使用到了 map(Function<? super T, ? extends U> mapper)
Optional.ofNullable(orderInfo)
.map(Order::getAddress)
.map(Address::getCity)
我们先来介绍一下它的:
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 boolean isPresent() {
return value != null;
}
其实这段源码很简答,先是做个空值检查,接着就是 value 的存在性检查,最后就是应用函数并返回新的
Optional```
跟.map
相似的,还有个 flatMap
,如下:
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));
}
}
可以发现,它两差别并不是很大,主要就是体现在入参所接受类型不一样。
2.4 isPresent 和 ifPresent
我们在使用 Optional 的过程中呢,有些时候,会使用到 isPresent
和 ifPresent
,他们有点像,一个就是判断 value 值是否为空,��外一个就是判断 value 值是否为空,再去做一些操作。比如:
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
即判断 value 值是否为空,然后做一下函数式的操作。
举个例子,这段代码:
if(userInfo!=null){
doBiz(userInfo);
}
用了 isPresent
可以优化为:
Optional.ofNullable(userInfo)
.ifPresent(u->{
doBiz(u);
});
优雅永不过时,嘻嘻~
- 点赞
- 收藏
- 关注作者
评论(0)