使用Guava优雅解决代码边界判断
2023年12月6日 · 1222 字 · 3 分钟
背景
在Java编程中需要对数据库操作、RPC请求等返回的数据进行空值判断,以避免空指针错误和数据越界等问题。 此外需要在边界情况下提前进行断言并包装友好的错误信息,以便向用户提供清晰的报错信息。
由于容易忽略边界情况的空值判断,每一步都需要考虑这些情况,导致模板代码过多,缺乏直观和统一的风格
现状code
public SceneInfo getSceneInfo(GetSceneInfoRequest request) {
// getPlanId 在调用方法入口 强制判空了
String planId = request.getPlanId();
TPlanEntity entity = tPlanMapper.getPlanInfo(planId);
logger.info("预案信息 planEntity:{}", JsonUtils.toJsonString(planEntity));
// 判断是否为null
if (entity == null) {
throw new BizException("预案不存在");
}
SceneInfo info = new SceneInfo();
String sceneName = planEntity.getSceneName();
if (StringUtils.isNotBlank(sceneName)) {
List<SceneDto> sceneDtoList = RedHaClient.sceneDtoMap.get(sceneName);
// 判断是否list是否为空
if (sceneDtoList == null || sceneDtoList.isEmpty()) {
throw new BizException("预案绑定的业务场景不存在");
}
sceneDtoList.stream()
.findFirst()
.ifPresent(
dto -> {
info.setName(dto.getName());
info.setNameZh(dto.getNameZh());
});
}
// 校验预案是否绑定的业务场景id
Integer id = planEntity.getSceneId();
// 继续判断
if (id == null || id == 0) {
throw new BizException("该预案没有绑定业务场景");
}
// 查询预案绑定的业务场景信息
SceneEntity entity = sceneService.getSceneEntity(id);
String sceneZhName = entity.getNameZh();
String sceneZhName = entity.getNameZh();
// 继续判断
if (sceneZhName == null || sceneZhName.equals("")) {
throw new BizException("该预案绑定的业务场景信息为空");
}
//xxxx其他操作
return info;
}
优雅处理边界byGuava
什么是Guava
Guava是由Google开发的Java集合库,旨在提供处理Java集合的实用工具。它包括许多功能,如基本工具、集合、不可变集合、新的集合类型、图形、缓存、功能习语、并发、字符串、原始类型、范围等。Guava的目标是减少编码错误,促进标准编码实践,并通过使代码简洁易读来提高生产效率;总的来说,Guava是一个功能强大的Java集合库,旨在简化Java编程,并提供各种实用工具和功能,以提高开发效率和减少错误。
show code (避免遗漏空值判断、精简代码减少模版代码)
public SceneInfo getSceneInfo(GetSceneInfoRequest request) {
String planId = request.getPlanId();
// 查询预案信息
// 链式方式获取数据时候,顺便判断边界条件 + 不符合条件的报错信息
TPlanEntity planEntity =
Preconditions.checkNotNull(tPlanMapper.getPlanInfo(planId), "预案不存在 planId: %s", planId);
logger.info("预案信息 planEntity:{}", JsonUtils.toJsonString(planEntity));
// 新预案有记录ha业务场景name直接返回
SceneInfo info = new SceneInfo();
String sceneName = planEntity.getSceneName();
if (StringUtils.isNotBlank(sceneName)) {
// 链式方式获取数据时候,顺便判断边界条件 + 不符合条件的报错信息
List<SceneDto> sceneDtoList =
Preconditions.checkNotNull(
RedHaClient.sceneDtoMap.get(sceneName), "该预案绑定的业务场景英文映射在HA平台不一致");
// 这里获取sceneDtoList 保证百分之百不为空
sceneDtoList.stream()
.findFirst()
.ifPresent(
dto -> {
info.setName(dto.getName());
info.setNameZh(dto.getNameZh());
});
return info;
}
// 校验预案是否绑定的业务场景id
// 使用Optional包装返回数据,强制下一步判断边界,现有api名称见面直意
Optional<Integer> sceneIdOptional = Optional.ofNullable(planEntity.getSceneId());
if (!sceneIdOptional.isPresent() || sceneIdOptional.get() == 0) {
throw new BizException("该预案没有绑定业务场景");
}
// 查询预案绑定的业务场景信息
SceneEntity entity = sceneService.getSceneEntity(sceneIdOptional.get());
String sceneZhName = entity.getNameZh();
if (Strings.isNullOrEmpty(sceneZhName)) {
throw new BizException("该预案绑定的业务场景信息为空");
}
// 或者这个case
// 期望数据为true,不满足则报错
// Preconditions.checkArgument(!Strings.isNullOrEmpty(sceneZhName), "预案绑定的业务场景信息为空");
// xxxx其他操作
return info;
}
Quick Start
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>