简介
一个避免NPE的神器
String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();
这行代码一般而言,你只敢向下面这么写
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
if (isocode != null) {
isocode = isocode.toUpperCase();
}
}
}
}
但是使用Optional进行简化后
String result = Optional.ofNullable(user)
.flatMap(User::getAddress)//这个函数输出是一个Optianal的对象
.flatMap(Address::getCountry)//这个函数输出的也是一个Optioanl对象。
.map(Country::getIsocode)
.orElse("default");
原理
public final class Optional<T> {
//如果是null,返回一个Optional<输入类型>的空实例。否则输出Optional<输入类型>的输入的包装Optionl对象。
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
private static final Optional<?> EMPTY = new Optional<>();
//function范型中第一个是入参,第二个是返回值。
//flatMap和map接受的fuction,入参数必须是当前Optional类范型T的父类。这是很自然的。
//区别在于,flatMap要求函数输出的Optional对象,必须是Optioanl的包装,而map要求是U的子类。
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));
}
}
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 static void main(String[] args) throws Exception{
A a = new A();
String x = Optional.ofNullable(a).map(A::getB).map(B::getC).map(C::getD).orElse("default");
System.out.println(x);
}
@Getter
@Setter
static class A{
B b;
}
@Getter
@Setter
static class B{
C c;
}
@Getter
@Setter
static class C{
String d;
}