JDK8 Optional优雅的判空操作

news2025/1/18 14:26:34

一、前言

在我们编程过程中因为疏忽经常会遇到NullPointerException空指针异常,所以与此同时就避免不了对变量一层一层的进行判空。JDK8新特性所提供的Optional类,可以让我们更优雅的进行判空操作。学习其的意义就是提醒开发者注意空值情况,并在一定程度上优雅处理问题。
例如下图传统判空:
传统判空,下文会展示次写法的解决方案
如上图,一旦代码量大起来了,条件多了,代码就会变得很冗余,变得难以维护,通过使用Optional就可以很好的处理,让我们继续了解。.
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

二、Optional API介绍

首先了解一下Optional为我们提供使用的方法:

在这里插入图片描述
在这里插入图片描述

三、Optional实战

1、对象操作

Optional.of()和Optional.ofNullable()用法相似。
Optional.of()创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException,而Optional.ofNullable()允许传null。
后续以Optional.ofNullable()为例,展示使用optional和不使用的不同写法

1.1 ifPresent(不为null则运行函数体)

如果user不为null则调用其他的方法或操作,例如:

 User user = userService.getById("123456");
 //未使用Optional
  if (user != null){
  	   //执行user不为null的逻辑
       System.err.println(user.getUserName());
   }
// 使用Optional
 Optional.ofNullable(user).ifPresent(u -> System.out.printf(u.getUserName()));

1.2 filter(条件过滤)

    User user = userService.getById("02BEC97B_4CE3_5E6B_7A4C_B03A26D93A9E");
    		//未使用Optional
    if (user != null){
        if (user.getUserName().equals("默认用户")){
            System.out.println("这个是默认用户");
        }
    }
    // 使用Optional
    Optional.ofNullable(user).filter(u-> StringUtils.equals(u.getUserName(),"默认用户")).ifPresent(
            u-> System.out.println("这个是默认用户")
    );

1.3 map+orElse(提取对象属性值,为null提供默认值)

//optional+orElse
String name = Optional.ofNullable(user).map(User::getUserName).orElse("名字为空");

使用map就可以很好的解决逐层判空的目的,例如本文首图示例,用户对象下有教师对象,教师对象下有年轻教师对象,需要获取年轻教师的名字,常规写法则需要先判断用户是否为null,再逐层判断教师、年轻教师对象是否为null,最终取出想要的值。
例如:

//未使用optional
User user = userService.getById("102BEC97B_4CE3_5E6B_7A4C_B03A26D93A9E");
String name = "";
if (user != null) {
    Teacher teacher = user.getTeacher();
    if (teacher != null) {
        YoungTeahcer youngTeacher = teacher.getYoungTeacher();
        if (youngTeacher != null) {
 	        name = youngTeacher.getName();
        }
    }
}
//使用optional
String youngTeacherName = Optional.ofNullable(user)
    .map(User::getTeacher)
    .map(Teacher::getYoungTeacher)
    .map(YoungTeacher::getName).orElse("未查到");

1.4 map+ ifPresent(可用于逐层判断,执行对象属性值不为null之后的逻辑)

//未用optional
User user = userService.getById("102BEC97B_4CE3_5E6B_7A4C_B03A26D93A9E");
if (user!=null){
    if (StringUtils.isBlank(user.getUserId())){
    //执行用户id不为空的逻辑
        System.err.println("111");
    }
}
//使用optional
Optional.ofNullable(user).map(User::getUserName).ifPresent(t-> System.err.println(t));

1.5 map+orElseThrow(提取对象属性值,为null抛异常)

Optional.ofNullable(user).map(User::getUserName).orElseThrow(() ->  new RuntimeException("查询为空"));

1.6 flatMap(Optional对象进行二次包装)

Optional.ofNullable(byId).flatMap(u -> Optional.ofNullable(u.getUserName()));

2、集合操作(集合判空不建议使用optional)

2.1 集合遍历(建议使用CollectionUtil工具类等,例如new List() 使用optional判断值不是null,则会出现问题。)

List<User> list = userService.list();
//未用optional
if (CollectionUtils.isEmpty(list)){
    list.forEach(u->{
        System.out.println(u.getUserName());
    });
}
//使用optional
Optional.ofNullable(list).orElse(new ArrayList<>()).forEach(user -> System.out.println(user.getUserName()));

四、注意事项

上述例子可以看到Optional的相关api可以结合具体场景组合使用,从而达到判空以及简化代码量的目的,但是Optional在一定场景很好用,但其实很多时候简单的if判断同样可以解决问题,反而使用optional不利于可读性,所以更需要从代码的可读性结合具体场景出发。

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

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

相关文章

怎么自己制作动图表情包?在线gif生成的操作步骤

gif表情包在我们平时的生活里斗图的时候经常会用到&#xff0c;那么如何用图片制作gif&#xff08;https://www.gif.cn&#xff09;表情包呢&#xff1f;今天就分享一个在线gif生成的简单方法&#xff0c;利用gif制作工具将图片转gif动图&#xff0c;下面是详细的操作步骤。 打…

爬楼梯(一次爬1或2层)

一&#xff0c;题目描述 二&#xff0c;解题思路 动态规划 动规五部曲&#xff1a; 1. 确认dp数组以及下标含义 2. 推导递推公式 3. 确认dp数组如何初始化 4. 确认遍历顺序 5. 打印dp数组 dp数组含义&#xff1a;到第i层的方法数目 下标含义&#xff1a;层数 递推公式&…

2023年服贸会在哪里举行?北京有哪些媒体可以做宣传?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 8月14日&#xff0c;”2023年服贸会新闻发布会在北京首钢园举行&#xff0c;宣布2023年服贸会将于9月2日至6日在国家会议中心和首钢园区举办&#xff0c;采用‘线下线上’‘综合专题’办…

跳跳!(贪心)

题目描述 你是一只小跳蛙&#xff0c;你特别擅长在各种地方跳来跳去。 这一天&#xff0c;你和朋友小 F 一起出去玩耍的时候&#xff0c;遇到了一堆高矮不同的石头&#xff0c;其中第 i 块的石头高度为 h_i&#xff0c;地面的高度是 h_0 0。你估计着&#xff0c;从第 i 块石…

eNSP:mplsvpn综合实验

要求完成下图实验&#xff1a; 拓扑信息标注&#xff1a; 命令操作&#xff1a; r1: <Huawei>sys [Huawei]sys r1 [r1]int lo0 [r1-LoopBack0]ip add 192.168.1.1 24 [r1-LoopBack0]int g 0/0/0 [r1-GigabitEthernet0/0/0]ip add 192.168.2.1 30[r1]ip route-static 19…

【BASH】回顾与知识点梳理(二十九)

【BASH】回顾与知识点梳理 二十九 二十九. 进程和工作管理29.1 什么是进程 (process)进程与程序 (process & program)子进程与父进程&#xff1a;fork and exec&#xff1a;进程呼叫的流程系统或网络服务&#xff1a;常驻在内存的进程 29.2 Linux 的多人多任务环境多人环境…

C#__委托的基本用法

// 委托A class DelegateA{// 委托&#xff0c;一个类型&#xff0c;可以赋值一个方法的引用// 定义delegate void Tool(int x);delegate long ToolLong(long x, long y);delegate string GetString();public void Delegate(){// 赋值Tool tool null;ToolLong toollong null…

clickhouse 集群搭建

目录 一、 首先要安装单节点集群 二、安装zookeeper并搭建集群 1. 配置host 2. 安装zookeeper 3. 配置zookeeper 三、clickhouse 集群配置 1.配置metrika.xml文件 2. 修改clickhouse的配置文件 一、 首先要安装单节点集群 在这里就不太赘述。官网下载安装包&#xff0…

离线安装Nginx(rpm方式)

环境&#xff1a;centos7.9 下面将展示通过rpm方式安装Nginx 1.官方下载Nginx rpm包 下载地址 http://nginx.org/packages/ 下载版本根据操作系统版本进行选择&#xff0c;本次操作系统是centos7.9 - 64位系统&#xff0c;所以对应的下载路径是&#xff1a; http://nginx.or…

视频监控管理平台EasyCVR视频平台通过navicat修改登录密码的具体操作步骤

TSINGSEE青犀视频监控管理平台EasyCVR可以根据不同的应用场景需求&#xff0c;让平台在内网、专网、VPN、广域网、互联网等各种环境下进行音视频的采集、接入与多端分发。在视频能力上&#xff0c;平台可实现视频实时直播、云端录像、云存储、回放与检索、告警上报、视频快照、…

OJ练习第147题——字符串中的查找与替换

字符串中的查找与替换 力扣链接&#xff1a;833. 字符串中的查找与替换 题目描述 你会得到一个字符串 s (索引从 0 开始)&#xff0c;你必须对它执行 k 个替换操作。替换操作以三个长度均为 k 的并行数组给出&#xff1a;indices, sources, targets。 要完成第 i 个替换操…

RDMA Send Receive操作

1. 前言 RDMA指的是远程直接内存访问&#xff0c;这是一种通过网络在两个应用程序之间搬运缓冲区里的数据的方法。RDMA与传统的网络接口不同&#xff0c;因为它绕过了操作系统。这允许实现了RDMA的程序具有如下特点&#xff1a; 绝对的最低时延最高的吞吐量最小的CPU足迹 &am…

《游戏编程模式》学习笔记(四) 观察者模式 Observer Pattern

定义 观察者模式定义了对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 这是定义&#xff0c;看不懂就看不懂吧&#xff0c;我接下来举个例子慢慢说 为什么我们需要观察者模式 我们看一个很简…

二叉树的构建及遍历

题目链接:https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId60&&tqId29483&rp1&ru/activity/oj&qru/ta/tsing-kaoyan/question-ranking 题目 编一个程序&#xff0c;读入用户输入的一串先序遍历字符串&#xff0c;根据此字符串建…

视频播放相关记录

一、场景 App应用测试在二次回归时&#xff0c;提出了安卓端视频定位不准的问题。 二、分析 代码层面使用了安卓原始的MediaPlayer中的seekTo接口来定位&#xff1a; mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {Overridepublic boolean onInfo(MediaPlayer mp, i…

多旋翼飞控底层算法开发系列实验 | 多旋翼动力系统设计实验1

多旋翼飞控底层算法开发系列实验 | 多旋翼动力系统设计实验1 01 多旋翼动力系统简介 多旋翼无人机的动力系统通常包括螺旋桨、电机、电调以及电池。动力系统是多旋翼最重要的组成部分&#xff0c;它决定了多旋翼的主要性能&#xff0c;如悬停时间、载重能力、飞行速度和飞行距…

The kernel appears to have died. It will restart automatically.

在使用pytorch运行一个小案例时&#xff0c;绘制图像时出现了 The kernel appears to have died. It will restart automatically. 查看 anaconda prompt OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized. OMP: Hint This means…

NestJs 中使用 mongoose

在 NestJS 中链接 MongoDB 有两种方法。一种方法就是使用TypeORM来进行连接&#xff0c;另外一种方法就是使用Mongoose。 此笔记主要是记录使用Mongoose的。所以我们先安装所需的依赖&#xff1a; npm i nestjs/mongoose mongoose安装完成后&#xff0c;需要在AppModule中引入…

前端基础学习笔记

目录 1.HTML部分1.HTML简介2.实例介绍3.标题4.段落5.链接6.图像7.表格8.速查列表1.基本文档2.基本标签3.文本格式化4.链接5.图片6.无序列表7.有序列表8.定义列表9.表格10.框架11.表单 2.CSS部分1.CSS简介1.什么是CSS2.为什么使用CSS3.CSS作用 2.基本用法1.CSS语法2.CSS应用方式…

Failed to resolve component: v-data-table“. vue3 + vuefity 使用 v-data-table 报错解决

在使用 vue3 vuetify 开发项目的过程中用到了 v-data-table 组件&#xff0c;结果在使用的过程中发现加载失败控制台报错。 [Vue warn]: Failed to resolve component: VDataTable解决方案&#xff1a; import { VDataTable } from vuetify/labs/VDataTable参考文档: https:…