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时时不易理解的部分在实践中也有了一番新的的认识。继续严格要求自己,争取码出一手优雅的代码。

相关推荐
luckywuxn13 分钟前
EurekaServer 工作原理
java·eureka
壹米饭16 分钟前
Java程序员学Python学习笔记一:学习python的动机与思考
java·后端·python
java金融18 分钟前
Java 锁升级机制详解
java
Young556621 分钟前
还不了解工作流吗(基础篇)?
java·workflow·工作流引擎
让我上个超影吧23 分钟前
黑马点评【缓存】
java·redis·缓存
ajassi200031 分钟前
开源 java android app 开发(十一)调试、发布
android·java·linux·开源
YuTaoShao1 小时前
Java八股文——MySQL「存储引擎篇」
java·开发语言·mysql
crud1 小时前
Java 中的 synchronized 与 Lock:深度对比、使用场景及高级用法
java
王德博客1 小时前
【Java课堂笔记】Java 入门基础语法与面向对象三大特性详解
java·开发语言
seventeennnnn1 小时前
Java大厂面试真题:谢飞机的技术挑战
java·spring boot·面试·aigc·技术挑战·电商场景·内容社区