NullPointerException,总会爆出文明的两个字,然后感叹一番,这里怎么可能会空指针啊。不接受反驳,反驳就是你还不够"专业",或者经验太少,被鞭打得少了。
NullPointerException,但是我们还是要尽自己最大努力去避免踩坑。如果按照传统的代码,我们通常会写出下面这些代码
public int parseInt(String num) {
if (num == null || "".equals(num)) {
return 0;
}
return Integer.parseInt(num);
}
咋一看好像没啥毛病,既判断了非空,也判断了空的字符串,但是如果后面还有parseDouble(String num)、parseLong(String num)、parseXXX(String num)方法,我想你会奔溃的,而且总是写一样的代码。
Optional类,看到这里大家就该知道了,这次的代码都是针对jdk8以上的,jdk8以下的兄弟就对不起了,让你们看了这么久的废话。
Optional类的源码,Optional主要有三个静态方法
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
empty方法是用来构建一个空的Optional对象,of方法是构建一个值为value的Optional对象,值得注意的是这里面的value不能为空,否则又会抛出NullPointerException,这可与我们今天的目标相向,所以今天我们的主角是ofNullable方法。ofNullable方法很简单,如果value为空则调用empty方法创建一个空的,如果value不为空则调用of方法创建。这简直就是这两兄弟的集大成者啊,这两兄弟能做的事它能做,这两兄弟不能做到的事它也能做啊。但是使用ofNullable方法还有个不足的地方,他只能判断值是不是null,判断不了值为空字符串啊,这时候我们就可以基于Optional做二次开发了,所谓站在巨人的肩膀上就是这一刻了。
//新建个OPtionalUtil的工具类,提供一个静态方法判断字符串是不是空或者null
public static Optional<String> ofNullOrEmpty(String value) {
return value == null || "".equals(value) ? Optional.empty() : Optional.of(value);
}
//这时候我们的parseInt方法就可以这么写了
public int parseInt(String num) {
return Integer.parseInt(OptionalUtil.ofNullOrEmpty(num).orElse("0"));
}
ofNullOrEmpty方法是不是很眼熟,没错,就是在ofNullable方法的基础上加上一些判断条件,但是这样我们就有很多好玩的了,比如我们有个方法返回了个List,有时候我们就只需要获取到第一个条记录的某个属性就可以了,这时候我们就要写这样的代码了
public String getUserName(String userId) {
List<UserVo> userVoList = getUserByIds(Collections.singletonList(userId));
if (userVoList != null && userVoList.size() > 0)
return userVoList.get(0).getUserName();
return null;
}
但是我们同样可以和String判断一样,加一个空集合判断
public static <T> Optional<List<T>> orEmptyList(List<T> resultList) {
return resultList == null || resultList.size() == 0 ? Optional.empty() : Optional.of(resultList);
}
//我们的获取用户名方法就可以变成这个样子了
public String getUserName(String userId) {
return OptionalUtil.orEmptyList(getUserByIds(Collections.singletonList(userId)))
.map(l -> l.get(0).getUserName())
.orElse(null);
}
总而言之,Optional这个类还有很多可以拓展的地方,比如对map的判空,对一些业务参数的判断,而且能避免我们经常性的使用if else,代码显得更加地整洁,同时也能避免踩一些没必要踩的NullPointerException的坑,和乐而不用呢。