目录

一 Optional 是什么

二 Optional API介绍

三 Optional 最佳实践

3.1 不要直接返回 null,使用 Optional.empty();

3.2 正确使用 ifPresent()

3.3 少用 get(),多用orElse()和orElseGet()

3.4 少用of(),多用ofNullable()

四 Optional 常见用法


Optional 是什么

Optional 的作者 Brian Goetz 对这个 API 的说明:

Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result", and using null for such was overwhelmingly likely to cause errors.

为了避免 null 带来的错误,我们提供了一个可以明确表示空值的有限的机制。

Optional是一个容器,用于放置可能为空的值,它可以合理而优雅的处理null

Optional API介绍

public static<T> Optional<T> empty();  // 返回一个Optional容器对象public static <T> Optional<T> of(T value); // 创建一个Optional对象,如果 value 是 null,则抛出 NPEpublic static <T> Optional<T> ofNullable(T value); // 创建一个Optional对象,但 value 为空时返回Optional.empty()public T get(); // 返回Optional中包装的值,在判空之前,千万不要直接使用public boolean isPresent(); // 判断Optional中是否有值,返回 booleanpublic void ifPresent(Consumer<? super T> consumer); // 判断Optional中是否有值,有值则执行 consumer,否则什么都不干public T orElse(T other); // 返回Optional中包装的值,但不同的是当取不到值时,返回你指定的 defaultpublic T orElseGet(Supplier<? extends T> other); // 返回Optional中包装的值,取不到值时,返回你指定的 defaultpublic <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier); // 返回Optional中包装的值,取不到值时抛出指定的异常

Optional 最佳实践

Optional 属于返回类型,通常在业务返回值或者远程调用中使用。

3.1 不要直接返回 null,使用 Optional.empty()

// 使用Optional.empty()之前
private PoiTabHintDTO getPoiTabHintFromTask(FutureTask<PoiTabHintDTO> task) {if (Objects.isNull(task)) {return null;}try {return ThreadPoolUtils.get(task, 4, TimeUnit.SECONDS);} catch (Exception e) {log.error("getRdcPoiTabHintFromTask", e);Cat.logMetricForCount("getRdcPoiTabHintFromTask");return null;}
}// 使用Optional.empty()
private Optional<PoiTabHintDTO> getPoiTabHintFromTask(FutureTask<Optional<PoiTabHintDTO>> task) {if (Objects.isNull(task)) {return Optional.empty();}try {return ThreadPoolUtils.get(task, 4, TimeUnit.SECONDS);} catch (Exception e) {log.error("getRdcPoiTabHintFromTask", e);Cat.logMetricForCount("getRdcPoiTabHintFromTask");return Optional.empty();}
}
// 需要显示的从optional容器里面获取对象,能减少NPE的产生。

3.2 正确使用 ifPresent()

// 使用 ifPresent()之前
if (getPoiTabHintFromTask(rdcPoiHintTask).isPresent()) {poiTabHintList.add(getPoiTabHintFromTask(rdcPoiHintTask).get());
}
// 使用 ifPresent()
getPoiTabHintFromTask(rdcPoiHintTask).ifPresent(poiTabHintList::add);//性能没有提升,代码变得简洁。
3.3 少用 get(),多用orElse()和orElseGet()
// orElse()适用于入参是具体的值
public static ConfirmAuthorizationEnum getByCode(int code) {return Arrays.stream(ConfirmAuthorizationEnum.values()).filter(x -> code == x.getCode()).findFirst().orElse(ConfirmAuthorizationEnum.UNINITIALIZED);
}
// orElseGet()适用于lamda表达式
private Optional<DeliveryReturnBillBO> getReturnBillFromList(List<DeliveryReturnBillBO> allDeliveryReturnBillList, String returnBillNo) {return Optional.ofNullable(allDeliveryReturnBillList.stream().filter(deliveryReturnBillBO -> returnBillNo.equals(deliveryReturnBillBO.getReturnBillNo())).findFirst().orElseGet(() -> {log.error("未获取到退供单{}的详情信息", returnBillNo);Cat.logMetricForCount(DeliveryBill.RELATED_RETURN_BILL_IS_NULL);return null;}));
}
// 为啥少用 get(),需要结合判空使用,这和!=null其实没多大区别。

3.3 少用 get(),多用orElse()orElseGet()

// orElse()适用于入参是具体的值
public static ConfirmAuthorizationEnum getByCode(int code) {return Arrays.stream(ConfirmAuthorizationEnum.values()).filter(x -> code == x.getCode()).findFirst().orElse(ConfirmAuthorizationEnum.UNINITIALIZED);
}
// orElseGet()适用于lamda表达式
private Optional<DeliveryReturnBillBO> getReturnBillFromList(List<DeliveryReturnBillBO> allDeliveryReturnBillList, String returnBillNo) {return Optional.ofNullable(allDeliveryReturnBillList.stream().filter(deliveryReturnBillBO -> returnBillNo.equals(deliveryReturnBillBO.getReturnBillNo())).findFirst().orElseGet(() -> {log.error("未获取到退供单{}的详情信息", returnBillNo);Cat.logMetricForCount(DeliveryBill.RELATED_RETURN_BILL_IS_NULL);return null;}));
}
// 为啥少用 get(),需要结合判空使用,这和!=null其实没多大区别。

3.4 少用of(),多用ofNullable()

// 使用 of()场景
if (Objects.isNull(returnBillProcessBo)) {return Optional.empty();
}
return Optional.of(returnBillProcessBo);// 使用 ofNullable()场景
return Optional.ofNullable(returnBillProcessBo);

 Optional 常见用法

package com.example.demo.domain;import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 功能描述** @since 2022-09-23*/@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {// 兴趣id列表private List<Long> favList;// 标签列表private List<Tag> tagList;@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic static class Tag {private Long id;}/*** 获取兴趣id列表* @param user* @return*/public List<Long> getFavList(User user) {return Optional.ofNullable(user).map(User::getFavList).map(Collection::stream).orElse(Stream.empty()).filter(Objects::nonNull).collect(Collectors.toList());}/*** 获取标签id列表* @param user* @return*/public List<Long> getTagIdList(User user) {return Optional.ofNullable(user).map(User::getTagList).map(Collection::stream).orElse(Stream.empty()).map(Tag::getId).filter(Objects::nonNull).collect(Collectors.toList());}
}

Optional 最佳实践相关推荐

  1. Java8 Optional 最佳实践

    作者 | ES_her0 来源 | https://xie.infoq.cn/article/e3d1f0f4f095397c44812a5be 很多公众号其实都发过 Optional 的文章, 但大 ...

  2. Code Review最佳实践

    我一直认为Code Review(代码审查)是软件开发中的最佳实践之一,可以有效提高整体代码质量,及时发现代码中可能存在的问题.包括像Google.微软这些公司,Code Review都是基本要求,代 ...

  3. java微妙_10个微妙的Java编码最佳实践

    编写和维护jOOQ(Java中内部DSL建模的SQL)时遇到过这些.作为一个内部DSL,jOOQ最大限度的挑战了Java的编译器和泛型,把泛型,可变参数和重载结合在一起,Josh Bloch可能不会推 ...

  4. db2 参数标识符使用无效_在Python应用程序中使用配置的最佳实践

    大多数计算机应用程序都可以使用配置来指定行为,无论是通过命令行标志.环境变量还是配置文件.作为一名软件开发人员,处理配置时会遇到一些挑战,例如解析不合法的输入.验证它以及在程序的任意位置访问它.以Py ...

  5. Django开发准则与最佳实践

    最近在网易云课堂学习一门django高级实战教程,本文是学习课时14.15的一些笔记 Django开发准则与最佳实践 一.优先使用自定义用户模型 继承BaseUserManager和AbstractB ...

  6. 5万字长文:Stream和Lambda表达式最佳实践-附PDF下载

    文章目录 1. Streams简介 1.1 创建Stream 1.2 Streams多线程 1.3 Stream的基本操作 Matching Filtering Mapping FlatMap Red ...

  7. Baymard Institute:基于UX的最佳实践的光荣的,循证的工具

    重点 (Top highlight) I realized I wanted to write this piece when I mentioned the Baymard Institute to ...

  8. 可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践

     写在前面 为了不违反广告法,我竭尽全力,不过"最佳实践"确是标题党无疑,如果硬要说的话 只能是个人最佳实践. 问题引出 可能很多新手都会遇到同样的问题:我要我的Asp.net ...

  9. java微妙_编码Java时的10个微妙的最佳实践

    java微妙 这是10条最佳实践的列表,这些最佳实践比您的平均Josh Bloch有效Java规则要微妙得多. 尽管Josh Bloch的列表很容易学习,并且涉及日常情况,但此处的列表包含了涉及API ...

最新文章

  1. Levenshtein 相似度算法——Levenshtein(编辑距离)
  2. ExtJs grid合并单元格
  3. Python 之 Numpy (三)运算
  4. 数据流图中flow不显示文字_发动机系统数据流一般参数的解读
  5. boost::coroutine模块实现power的测试程序
  6. Redis实战(一):Redis一键安装脚本,Redis 介绍及 NIO 原理介绍
  7. ios 开发设置左滑退出_苹果铃声怎么设置自己的歌?教你用手机快速搞定!
  8. LeetCode 432. 全 O(1) 的数据结构(设计题)*
  9. 研究称语言能力比数学能力更重
  10. 建设数据中心机房主要看这几点,否则被定为劣质机房
  11. 案例分析|能源行业大数据案例分析
  12. 数据库索引选择的探索(二)之直方图
  13. Excel查看多列重复项
  14. 计算机 无法自检,电脑开机无法完成自检的原因分析
  15. 专家通过六点考证唐村《李氏族谱》:辨别家谱真伪,有这些窍门
  16. Graph Convolutional Neural Network - Spatial Convolution 图卷积神经网络 — 空域卷积详解
  17. 计算机动画就业前景,2020动画专业就业前景和就业方向分析
  18. 自动给多个视频进行画面裁切,裁剪成一样的尺寸
  19. 初识MIMO(三):天线分集技术及其仿真
  20. RuntimeError: Python 3.5 or later is required

热门文章

  1. 1下-21-5月-2
  2. 道听途说(持续更新)
  3. 计算机无法识别机qie硬盘,(普及知识)让数据无法恢复的秘密(资料完全粉碎)...
  4. 浅析 | 低代码在海岸TDM中的实际应用(平台后端架构)
  5. 什么是4K镜头?4K镜头优势是什么?
  6. MM2018/风格迁移-Style Separation and Synthesis via Generative Adversarial Networks通过生成性对抗网络进行风格分离和合成
  7. unigui中创建freeform并被fram调用
  8. 0108 --qq 时间的隐藏
  9. 选择物流快递业PDA手持终端的5个重要因素
  10. 如何禁止wifi万能钥匙连接我的路由器?