前言:
Optional 是 Java 8 的新特性,专治空指针异常(NullPointerException, 简称 NPE)问题,它是一个容器类,里面只存储一个元素(这点不同于 Conllection)。
为方便用户通过 Lambda 表达式调用 Optional 的方法,部分方法(如:filter、ifPresent、map、orElseGet)需传入函数式接口(如:Predicate、Consumer、Function、Supplier)参数。
项目场景:
业务需求是这样的,从第三方拉取用户信息,然后保存到公司自己的数据库,而第三方接口返回的数据是 JSON 格式的,需要获取到用户地址相关信息,但是用户地址相关信息却藏的十分深,如下面所示,JSON 节点是这样的:
{"userInfo":{"userDetails":{"city":"深圳市"}}}
基本实现
创建相关实体用来接收
import lombok.Data;
@Data
public class User {
private Integer id; // id
private UserInfo userInfo; // 用户信息
public User(UserInfo userInfo) {
this.userInfo = userInfo;
}
}
import lombok.Data;
@Data
public class UserInfo {
private String userName; // 用户名称
private UserDetails userDetails; // 用户详情
public UserInfo(UserDetails userDetails) {
this.userDetails = userDetails;
}
}
import lombok.Data;
@Data
public class UserDetails {
private String address; // 住址
private String city; // 城市
public UserDetails(String city) {
this.city = city;
}
}
示例代码:
1.常用的写法
缺点:if嵌套非常深
import com.test.entity.User;
import com.test.entity.UserDetails;
import com.test.entity.UserInfo;
import java.util.Optional;
public class TestService {
public static void main(String[] args) {
UserDetails userDetails = new UserDetails("深圳市");
UserInfo userInfo = new UserInfo(userDetails);
User user = new User(userInfo);
System.out.println(getCity(user));
}
/**
* 以前的写法
* @param user 用户对象
* @return 用户所在城市
*/
public static String getCity(User user){
if(user != null){
UserInfo userInfo = user.getUserInfo();
if(userInfo != null){
UserDetails userDetails = userInfo.getUserDetails();
if(userDetails != null){
return userDetails.getCity();
}
}
}
return null;
}
}
2.JAVA8写法
优点:不用再额外判断空指针
import com.test.entity.User;
import com.test.entity.UserDetails;
import com.test.entity.UserInfo;
import java.util.Optional;
public class TestService {
public static void main(String[] args) {
UserDetails userDetails = new UserDetails("深圳市");
UserInfo userInfo = new UserInfo(userDetails);
User user = new User(userInfo);
System.out.println(getCity_java8(user));
}
/**
* java8写法
* @param user 用户对象
* @return 用户所在城市
*/
public static String getCity_java8(User user){
return Optional.ofNullable(user)
.map(u -> u.getUserInfo())
.map(d -> d.getUserDetails())
.map(t -> t.getCity())
.orElse(null);
}
}
源码解析:
为什么Optional不用判断空指针了呢,其实这并没有用什么高超的技术,看源码可以发现其实是它已经帮我们处理好了
1.映射元素(map)
//将 T 类型元素映射为 U 类型元素
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));
}
}
2.创建容器(ofNullable)
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
3.容器判空(isPresent)
// 判断 Optional Value 有没有值
public boolean isPresent() {
return value != null;
}