Java之Optional使用姿势二

Optional是一种显式地避免出现空指针的操作,就如我们在实际开发中如果遇到方法返回值是集合的情况下不是返回null,而是返回一个空的集合一样,事实上,如果方法的返回值如果是普通对象,我们也不应该返回null,而是返回一个被包装的Optional对象,例如返回Optional< User >。Optional不仅仅提供了常规的避免空指针的方法,还提供了一些简单的流式操作,能够实现一些常规的链式操作。以下,记录一些工作中的使用心得。

1、背景:

以用户管理模块举例,一个用户可能有多种角色,一个角色又可能有多种权限。当在用户管理界面希望查询到某一用户的所有角色以及权限。项目分层:Controller->Service->Repository->Mapper。

2、Optional.of()与Optional.ofNullable():

Optional.of()方法用于确定被包装的对象一定不为null的场景,而Optional.ofNullable()方法则用于不确定被包装的对象是否为null的场景

1.1、Optional.ofNullable():

场景一: 例如,在Repository层根据用户id查询用户,并不能确定数据库中是否存在要查询的user,那么使用Optional.ofNullable()返回一个Optional对象,避免在上层使用时出现空指针。

代码:

java 复制代码
public Optional<User> getUserById(Integer userId) {
    return Optional.ofNullable(userMapper.selectById(userId));
} 

场景二:例如,调用日志模块的API在用户当日所有的操作日志中找到所有修改昵称的操作,将结果组装返回成一个指定的数据结构。我们无法确保查询结果一定不为null,所以需要用Optional.ofNullable()包装。

代码:

java 复制代码
public List<OperateLogInfo> getOperateLogInfo(Integer userId) {
    // getUpdateNickNameOperation调用日志模块的API,是否为null未知
    return Optional.ofNullable(getUpdateNickNameOperation(userId))
            .orElseGet(Collections::emptyList)
            .stream()// 省略stream之后的操作
            .map()
            .filter()
            .collect(Collectors.toList());
}

1.2、Optional.of():

例如,在Repository层中,在保存用户和角色关系的方法传入参数userRoleInfo(包含用户id,以及角色)用来保存一个用户的角色信息时所以我们可以使用Optional.of()方法去包装这个userRoleInfo,方便后续的流式操作。在此处就认为userRoleInfo绝对不为null,因为都已经在Repository层了,前面某层应当已经有了校验,这个参数就应当不为null。要注意快速失败原则,及早定位问题。

代码:

java 复制代码
public void saveUserRoleInfo(UserRoleInfo userRoleInfo) {
    Optional.of(userRoleInfo)
            .map(UserRoleInfo::getRoles)
            .ifPresent(roles -> {
                // 保存逻辑
            });
}

3、flatMap():

flatMap主要解决Optional嵌套的问题,例如:Optional<Optional<T>>,在使用Optional的流式编程过程中使用map操作可能会发生Optional的嵌套,而flatMap则会去掉多余的嵌套,只保留原始的Optional包装。与map操作相比,flatMap操作直接返回操作结果,而map操作则在返回结果前使用Optional进行一次包装。比如以下是更新用户地址的一段逻辑,先根据userId查询用户原有的地址,当地址不一样时进行更新。

代码:

java 复制代码
public void updateAddress(AddressInfo addressInfo) {
    Optional.of(addressInfo)
            .map(AddressInfo::getUserId)
            .flatMap(this::getAddressByUser)// getAddressByUser方法返回的对象是Optional的
            .filter()//省略比较逻辑
            .ifPresent(address -> {
                // 省略更新逻辑
            });
}

map操作与flatMap操作源码对比:

map:

flatMap:

4、总结:

Optional的出现与使用,极大的降低了发生空指针的概率,让程序的健壮性提升了不少,对刚接触Optional时时不易理解的部分在实践中也有了一番新的的认识。继续严格要求自己,争取码出一手优雅的代码。

相关推荐
叫我阿柒啊16 分钟前
Java全栈开发实战:从基础到微服务的深度解析
java·微服务·kafka·vue3·springboot·jwt·前端开发
凯尔萨厮33 分钟前
Java学习笔记三(封装)
java·笔记·学习
霸道流氓气质33 分钟前
Java开发中常用CollectionUtils方式,以及Spring中CollectionUtils常用方法示例
java·spring
失散1335 分钟前
分布式专题——5 大厂Redis高并发缓存架构实战与性能优化
java·redis·分布式·缓存·架构
通达的K35 分钟前
Java实战项目演示代码及流的使用
java·开发语言·windows
David爱编程42 分钟前
深入 Java synchronized 底层:字节码解析与 MonitorEnter 原理全揭秘
java·后端
索迪迈科技1 小时前
Protobuf 新版“调试表示为什么有链接?为什么会打码?我该怎么改代码?
java·log4j·apache
a_blue_ice1 小时前
JAVA 面试 MySQL
java·mysql·面试
月阳羊2 小时前
【硬件-笔试面试题-76】硬件/电子工程师,笔试面试题(知识点:H桥驱动电路的设计要点)
java·单片机·嵌入式硬件·面试·职场和发展
赵星星5202 小时前
MySQL的默认隔离级别:为什么是可重复读(RR)而非读已提交(RC)?
java