工作中经常会调外部接口、或者查询表等,如果对返回结果不进行空指针判断的话就会导致空指针异常。针对这种情况经常会使用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("杭州");
//使用mapString 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的作用就是为了获取对象中的具体值,如果对象不为空就继续获取对象里的值并返回