还在用 !=null 判空?让我们用Java8的全新API去优化代码吧

news2024/10/6 12:25:58

在这里插入图片描述

当我们编写Java代码时,经常需要处理空值(null),因为空值可能导致NullPointerException异常,这是一个常见的运行时异常。在Java 8中,引入了Optional类来更优雅地处理可能为空的值,从而减少NullPointerException的发生。在本篇博客中,我们将深入讨论Optional类的使用方法,并通过大量的示例来演示如何使用它来提高代码的可读性和稳健性。

什么是Optional?

Optional是Java 8中的一个新类,用于表示一个值可能存在也可能不存在的情况。它可以看作是一个容器,可以包含一个非空的值,也可以不包含任何值(即空值)。通过使用Optional,我们可以明确地处理这两种情况,而不是依赖于条件判断来检查空值。

创建Optional对象

Optional类中,有几种方式来创建Optional对象:

  1. 使用of(T value):如果我们确定值不会为空,可以使用of方法创建一个非空的Optional对象。如果传递了一个空值,将抛出NullPointerException
Optional<String> nonEmptyOptional = Optional.of("Hello, Optional!");
  1. 使用ofNullable(T value):如果值可能为空,可以使用ofNullable方法创建一个Optional对象。这个方法可以接受空值。
String nullableValue = getNullableValue(); // 可能为空的值
Optional<String> optional = Optional.ofNullable(nullableValue);
  1. 使用empty():创建一个空的Optional对象。
Optional<String> emptyOptional = Optional.empty();

访问Optional中的值

我们可以使用以下方法来访问Optional对象中的值:

  1. get():获取Optional对象中的值。但要小心,如果Optional为空,调用get()方法将抛出NoSuchElementException异常。
Optional<String> optional = Optional.of("Hello, Optional!");
String value = optional.get(); // 获取值
  1. orElse(T other):如果Optional为空,返回指定的默认值。
Optional<String> optional = Optional.empty();
String value = optional.orElse("Default Value"); // 使用默认值
  1. orElseGet(Supplier<? extends T> other):如果Optional为空,可以使用orElseGet方法提供的函数生成默认值。这种方式可以用来延迟计算默认值。
Optional<String> optional = Optional.empty();
String value = optional.orElseGet(() -> generateDefaultValue()); // 使用默认值生成函数
  1. orElseThrow(Supplier<? extends X> exceptionSupplier):如果Optional为空,可以使用orElseThrow方法抛出指定的异常。
Optional<String> optional = Optional.empty();
String value = optional.orElseThrow(() -> new IllegalStateException("Value is empty"));

判断Optional是否包含值

我们可以使用以下方法来判断Optional是否包含值:

  1. isPresent():如果Optional包含值,返回true,否则返回false
Optional<String> optional = Optional.of("Hello, Optional!");
boolean isPresent = optional.isPresent(); // true
  1. ifPresent(Consumer<? super T> consumer):如果Optional包含值,执行指定的操作。
Optional<String> optional = Optional.of("Hello, Optional!");
optional.ifPresent(value -> System.out.println("Value: " + value));

使用Optional的链式操作

当使用Optional的链式操作时,我们可以将一系列操作连接在一起,以更清晰和流畅的方式处理值。这种方法可以有效地避免繁琐的条件检查和嵌套,提高代码的可读性和简洁性。以下是一些示例,详细解释和分析Optional链式操作的用法:

示例 1: 获取用户的姓名

假设我们有一个User对象,但它可能为空。我们想从中获取用户的姓名,如果用户为空或姓名为空,则使用默认值。

User user = getUser(); // 可能为空的User对象

String userName = Optional.ofNullable(user) // 将User包装成Optional
    .map(u -> u.getName()) // 获取用户的姓名
    .orElse("Unknown"); // 如果为空,使用默认值

System.out.println("User Name: " + userName);
  • Optional.ofNullable(user) 将可能为空的user对象包装成Optional

  • map(u -> u.getName())Optional中获取用户的姓名。如果user为空,map操作会被跳过,不会导致NullPointerException。

  • orElse("Unknown") 用于指定默认值,如果用户为空或姓名为空,则返回默认值。

示例 2: 处理嵌套的数据

有时,我们可能有一个嵌套的数据结构,如User对象内部包含Address对象。我们想要获取用户的城市信息,但任何层级的数据都可能为空。

User user = getUser(); // 可能为空的User对象

String city = Optional.ofNullable(user) // 将User包装成Optional
    .flatMap(u -> Optional.ofNullable(u.getAddress())) // 获取Address对象,可能为空
    .map(address -> address.getCity()) // 获取城市信息
    .orElse("Unknown"); // 如果为空,使用默认值

System.out.println("City: " + city);
  • Optional.ofNullable(user) 将可能为空的user对象包装成Optional

  • flatMap(u -> Optional.ofNullable(u.getAddress())) 用于获取嵌套的Address对象,这里使用flatMap以平滑处理可能为空的情况。

  • map(address -> address.getCity())Optional中获取城市信息。如果useraddress为空,map操作会被跳过,不会导致NullPointerException。

  • orElse("Unknown") 用于指定默认值,如果城市信息为空,则返回默认值。

示例 3: 处理集合中的Optional

有时,我们可能在集合中包含Optional,需要从中提取数据并进行处理。例如,我们有一个包含可能为空的用户的列表,我们想获取他们的姓名,并将姓名连接成一个字符串。

List<Optional<User>> userList = getUserList(); // 包含可能为空的User的列表

String userNames = userList.stream()
    .map(optionalUser -> optionalUser
        .map(User::getName) // 获取用户的姓名,可能为空
        .orElse("Unknown")) // 如果为空,使用默认值
    .collect(Collectors.joining(", ")); // 连接姓名

System.out.println("User Names: " + userNames);
  • map(optionalUser -> ...)中,我们首先使用内部的map操作获取用户的姓名。如果optionalUser为空,则内部的map操作会被跳过,不会导致NullPointerException。

  • orElse("Unknown") 用于指定默认值,如果姓名为空,则返回默认值。

  • 最后,我们使用collect方法将所有的姓名连接成一个字符串,用逗号分隔。

这些示例演示了如何使用Optional的方法链式地处理数据。通过合理利用mapflatMaporElse等方法,我们可以在不担心空值的情况下处理数据,代码更具可读性和健壮性。这有助于简化代码并减少空指针异常的风险。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1048786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NOSQL Redis十大数据类型

String 字符串 string 是redis最基本的类型&#xff0c;而是使用最多的数据类型&#xff0c; 一个 key 对应一个 value string 类型是 二进制安全的&#xff0c;意思reidis 的string 可以包含任何数据&#xff08;任何数据都可以转换binary的&#xff09;&#xff0c;比如jpg图…

推荐一个好用的电商开源项目yudao源码

1、项目下载cloneruoyi-vue-pro: &#x1f525; 官方推荐 &#x1f525; RuoYi-Vue 全新 Pro 版本&#xff0c;优化重构所有功能。基于 Spring Boot MyBatis Plus Vue & Element 实现的后台管理系统 微信小程序&#xff0c;支持 RBAC 动态权限、数据权限、SaaS 多租户、…

使用日志分析工具了解网络情况

日志分析&#xff08;或日志文件分析&#xff09;是检查整个网络中生成的日志数据的过程&#xff0c;日志数据从各种来源生成&#xff0c;包括外围设备、工作站、服务器、应用程序以及其他硬件和软件组件&#xff0c;将它们收集到一个中心位置并进行分析&#xff0c;可以为了解…

提升工作效率的一些网站、应用、插件和小技巧(二)

前言 距离发布提升工作效率的一些网站、应用、插件和小技巧&#xff08;一&#xff09;已经过去了三年&#xff0c;这次再分享一下这三年里新 Get 到的一些工作、技巧&#xff0c;欢迎各位在评论区也分享一下自己使用的工具软件等&#xff0c;也希望下一个三年我还能继续坚持分…

蓝桥杯每日一题2023.9.28

AcWing 4409. 砍竹子 - AcWing 题目描述 题目分析 注&#xff1a;sqrtl的范围为long double&#xff0c;比sqrt更加精确 使用优先队列维护一段区间&#xff0c;如果连续一段相同就合并为一个区间&#xff0c;从大到小去枚举&#xff0c;每次先取出最大的一段&#xff0c;双…

MySQL到TiDB:Hive Metastore横向扩展之路

作者&#xff1a;vivo 互联网大数据团队 - Wang Zhiwen 本文介绍了vivo在大数据元数据服务横向扩展道路上的探索历程&#xff0c;由实际面临的问题出发&#xff0c;对当前主流的横向扩展方案进行了调研及对比测试&#xff0c;通过多方面对比数据择优选择TiDB方案。其次分享了整…

首批48所高校大模型开课“尝鲜”,AI教学赋能计划合作名单公布

为适应大模型时代快速迭代的人才需求&#xff0c;百度飞桨全新发布《AI教学赋能计划&#xff08;大模型特辑&#xff09;》&#xff0c;提供文心大模型、飞桨AI Studio星河社区、大模型课程资源、师资培训、高校竞赛等体系化支持&#xff0c;支持高校顺应时代潮流、共启大模型人…

LeetCode算法二叉树—116. 填充每个节点的下一个右侧节点指针

目录 116. 填充每个节点的下一个右侧节点指针 题解&#xff1a; 代码&#xff1a; 运行结果&#xff1a; 给定一个 完美二叉树 &#xff0c;其所有叶子节点都在同一层&#xff0c;每个父节点都有两个子节点。二叉树定义如下&#xff1a; struct Node {int val;Node *left;N…

爬虫抓取数据时显示超时,是爬虫IP质量问题?

当我们进行网络爬虫开发时&#xff0c;有时会遇到抓取数据时出现超时的情况。这可能是由于目标网站对频繁请求做了限制&#xff0c;或者是由于网络环境不稳定造成的。其中&#xff0c;爬虫IP的质量也是导致超时的一个重要因素。本文将探讨抓取数据时出现超时的原因&#xff0c;…

2023-9-28 JZ54 二叉搜索树的第k个结点

题目链接&#xff1a;二叉搜索树的第k个结点 import java.util.*;/** public class TreeNode {* int val 0;* TreeNode left null;* TreeNode right null;* public TreeNode(int val) {* this.val val;* }* }*/public class Solution {/*** 代码中的类名、方…

什么是大数据可视化

在互联网高速发展的当今&#xff0c;5G的兴起加速了数据传输的速度&#xff1b;与此同时&#xff0c;智能物联网如智慧家电、可穿戴设备等产品的火热&#xff0c;进一步扩充了数据获取的渠道。不仅仅在网页上、手机和电脑应用上以秒计产生海量数据&#xff0c;智能设备同时也在…

学习资源汇集

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 一、笔记软件 总结个人觉得好看并且简洁的软件&#xff0c;若是你觉得有更好的笔记软件&#xff0c;欢迎分享 Typora 最新版本收费…

【C/C++笔试练习】——常量指针和指针常量、位段的内存分配、统计输入的字母个数、排序子序列、倒置字符串

文章目录 C/C笔试练习1.常量指针和指针常量&#xff08;1&#xff09;常量指针和指针常量的定义&#xff08;2&#xff09;判别常量指针和指针常量&#xff08;3&#xff09;常量指针和指针常量的特性 2.结构体内存分配&#xff08;4&#xff09;位段的内存分配计算 3.完善程序…

【事务】事务的特性、并行事务有什么问题、事务的隔离级别等重点知识汇总

目录 事务的四大特性 并行事务会引发什么问题&#xff1f; 事务的隔离级别 事务的四大特性 原子性&#xff1a;一个事务中的所有操作&#xff0c;要么全部完成&#xff0c;要么全部不完成&#xff0c;不会结束在中间某个环节。事务在执行过程中发生错误&#xff0c;会被恢复…

目标检测算法改进系列之Backbone替换为EfficientFormerV2

EfficientFormerV2 随着视觉Transformers&#xff08;ViTs&#xff09;在计算机视觉任务中的成功&#xff0c;最近的技术试图优化ViT的性能和复杂性&#xff0c;以实现在移动设备上的高效部署。研究人员提出了多种方法来加速注意力机制&#xff0c;改进低效设计&#xff0c;或…

如何测试接口?首先你得知道如何开发接口。

接口测试&#xff1a;接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。&#xff08;来自某百科&a…

最全的QgraphicsEffect设置

在Qt中&#xff0c;QGraphicsEffect有四个子类&#xff0c;分别为QGraphicsBlurEffect, QGraphicsColorizeEffect, QGraphicsDropShadowEffect, and QGraphicsOpacityEffect&#xff0c;用于实现模糊、着色、阴影、透明度功能 下面就是对这四种功能以及效果做测试 1.QGraphicsB…

服务器搭建(TCP套接字)-libevent版(服务端)

Libevent 是一个开源的事件驱动库&#xff0c;用于开发高性能、并发的网络应用程序。它提供了跨平台的事件处理和网络编程功能&#xff0c;具有高性能、可扩展性和可移植性。下面详细讲解 Libevent 的主要组成部分和使用方法。 一、事件基础结构&#xff08;event_base&#x…

26530-2011 地理标志产品 崂山绿茶

声明 本文是学习GB-T 26530-2011 地理标志产品 崂山绿茶. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了崂山绿茶地理标志产品的术语和定义、保护范围、分类、等级和实物标准样、要求、试 验方法、检验规则、标志、标签、包装、…

遥遥领先!探索Amazon CodeWhisperer魔力,你的私人AI编程助手!

本文目录 【前言】一、Amazon CodeWhisperer 功能概览1.1 强大的代码建议1.2 支持多种语言与IDE1.3 安全扫描 二、沉浸式体验使用Amazon CodeWhisperer实战开发代码2.1 Pycharm中快速导入Amazon CodeWhisperer2.2 使用CodeWhisperer快速构建Python代码2.3 Amazon CodeWhisperer…