写业务代码的时候,通常会遇到数据库POJO对象转换为前端需要的VO对象,这时经常会遇到烦人的空指针问题,Java 8之前,我们可能这么写:
对于对象field复制风格:
a.setCreateTime(b.getCreateTime().getTime()); a.setAmount(b.getPayed()+b.getVoucher());
对于装饰器风格:
public Long getCreateTime() { return b.getCreateTime().getTime(); } public Long getAmount() { return b.getPayed()+b.getVoucher() }
很明显,这些代码会有空指针异常的风险.一般我们会这么修改:
对于对象field复制风格:
if (b.getCreateTime()!= null) { a.setCreateTime(b.getCreateTime().getTime()); } if (b.getPayed() != null) { a.setAmount(b.getPayed();
} else { a.setAmount(0L); } if (b.getVoucher() != null) { a.setAmount(a.getAmount()+b.getVoucher()); }对于装饰器风格:
public Long getCreateTime() { if (b.getCreateTime()!= null) { return b.getCreateTime().getTime(); } else { return null; } } public Long getAmount() { Long result = 0L; if (b.getPayed() != null) { result += b.getPayed(); } if (b.getVoucher() != null) { result += b.getVoucher(); } return result; }
Java8引入的Optional写法:
对于对象field复制风格:
Optional.ofNullable(b.getCreateTime()).ifPresent(timestamp -> a.setCreateTime(timestamp.getTime())); a.setAmount(Optional.ofNullable(b.getPayed()).orElse(0L) + Optional.ofNullable(b.getVoucher()).orElse(0L));
对于装饰器风格:
public Long getCreateTime() { Optional
createTime = Optional.ofNullable(b.getCreateTime()); if (createTime.isPresent()) { return createTime.get(); } else { return null; } } public Long getAmount() { return Optional.ofNullable(b.getPayed()).orElse(0L) + Optional.ofNullable(b.getVoucher()).orElse(0L) }
这样依然很复杂,尤其是嵌套多层之后。 更进一步,有没有通用简便的方法呢?联想到Java8的Functional Interface以及我们需要处理的异常只有空指针异常,可以写工具类:
import java.util.function.Supplier;
public class OptionalUtil {
/**
* 忽略NullPointerException的获取
* @param supplier
* @param <T>
* @return 如果有空指针,返回null
*/
public static <T> T orNull(Supplier<T> supplier) {
try {
return supplier.get();
} catch (NullPointerException e) {
return null;
}
}
/**
* 忽略NullPointerException的获取
*
* @param supplier
* @param or
* @param <T>
* @return 如果有空指针,返回or
*/
public static <T> T or(Supplier<T> supplier, T or) {
try {
T t = supplier.get();
if (t != null) {
return t;
}
return or;
} catch (NullPointerException e) {
return or;
}
}
}
这样,我们的代码就变得简洁多了:
对于对象field复制风格:
a.setCreateTime(OptionalUtil.orNull(() -> b.getCreateTime().getTime())); a.setAmount(OptionalUtil.or(() -> b.getPayed(), 0L) + OptionalUtil.or(() -> b.getAmount(), 0L));
对于装饰器风格:
public Long getCreateTime() { return OptionalUtil.orNull(() -> b.getCreateTime().getTime()); } public Long getAmount() { return OptionalUtil.or(() -> b.getPayed(), 0L) + OptionalUtil.or(() -> b.getAmount(), 0L); }