工作中经常会调外部接口、或者查询表等,如果对返回结果不进行空指针判断的话就会导致空指针异常。针对这种情况经常会使用if进行判断:
private boolean isNotNull(Object param) {
if (param == null) {
return false;
} else {
return true;
}
}
这样写其实功能上没有任何问题,但是如果需要判断的字段比较多,或者本身已经嵌套了多重循环或者判断,再加上这一层判断,代码就会变得非常臃肿,可读性非常差。
JDK1.8之后提出来Optional方法来解决这个问题,通过Optional方法,我们可以将上面的代码改造为以下方式:
private boolean isNotNull1(Object param) {
return Optional.ofNullable(param).isPresent();
}
这样看起来是不是优雅了很多,当然仅仅判断一个简单的对象就使用这个方法是远远不够的,再具体的工作中,我经常遇到的更多是像下面的这种代码:
public static void main(String[] args) {
List<String> list = null;
List<String> newList = Optional.ofNullable(list).orElse(new ArrayList());
newList.forEach(x -> System.out.println(x));
}
上面代码含义很简单:
如果list集合不为空,将list集合赋值给newList;如果list集合为空创建一个空对象集合赋值给newList,保证list集合永远不为空,也就避免了空指针异常。
下面我们看看底层是怎么处理的,怎么就避免了空指针呢?
首先看看.ofNullable方法源码:
private static final Optional<?> EMPTY = new Optional<>();
private Optional() {
this.value = null;
}
//如果对象为空,执行empty();不为空,执行of(value)
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
//empty()方法调用静态变量EMPTY生成一个空对象(不是null)
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
//of()方法生成一个有值的对象
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
其本质就是一系列三目运算,首先执行ofNullable()方法,如果T对象为空,执行empty()方法;不为空,执行of(value)方法;
empty()方法,初始化一个空对象Optional
of(value)方法,将泛型对象T用于Optional构造方法的参数上,返回一个有值的对象
经过以上几步,从而保证了Optional不为null,避免了空指针;
接下来看看最常用的.isPresent()、.orElse()、.map()方法的源码以及如何使用
- .isPresent()&.orElse()
//orElse
public T orElse(T other) {
return value != null ? value : other;
}
//isPresent
public boolean isPresent() {
return value != null;
}
- .map()
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));
}
}
map方法中最后一行代码为Optional.ofNullable,这是返回的时候自动把返回值包装好了
下面我们看看具体如何使用,isPresent和orElse已经在上面的代码中有所体现,下面我们看看map是怎么使用的
public class Demo01 {
public static void main(String[] args) {
Teacher teacher1 = new Teacher();
teacher1.setAddress("西湖");
teacher1.setCity("杭州");
//使用map
String s1 = Optional.ofNullable(teacher1).map(tempTeacher -> tempTeacher.getAddress())
.orElse("没有地址信息");
System.out.printf(s1.toString());
}
}
class Teacher {
private String address;
private String city;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
我们看一下运行结果:
所以map的作用就是为了获取对象中的具体值,如果对象不为空就继续获取对象里的值并返回