首页/新闻资讯/正文详情

java8中Optional使用

发布时间:2026/11/5 3:42:17 来源:云帆数科 栏目:资讯中心
java8中Optional使用
一、前言在Java中对一个空对象进行操作时便会抛出最常见的异常NullPointerException。为了改善这个问题Java 8中提供了一个java.util.Optional类型。Optional类的Javadoc描述如下这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true调用get()方法会返回该对象。下面介绍Optional类的使用方法。我们县创建好测试实体Address.javaDatapublicclassAddress{privateStringprovince;privateStringcity;privateStringarea;}User.javaDatapublicclassUser{privateStringname;privateStringphone;privateAddressaddress;}二、创建Optional2.1 创建一个空的Optional我们可以使用静态工厂方法Optional.empty创建一个空的Optional对象OptionalUseruserOptional.empty();2.2 根据非空值创建Optional我们也可以使用静态工厂方法Optional.of来创建一个非空对象的Optional对象OptionalUseruserOptional.of(user);如果user为空这段代码会立即抛出一个NullPointerException。2.3 创建可以为null的Optional使用静态工厂方法Optional.ofNullable我们可以创建一个允许null值的Optional对象OptionalUseruserOptional.ofNullable(user);如果user为空对其调用get方法将抛出NoSuchElementException。三、Optional方法3.1 Optional(T value),empty(),of(T value),ofNullable(T value)这四个函数之间具有相关性因此放在一组进行记忆。先说明一下Optional(T value)即构造函数它是private权限的不能由外部调用的。其余三个函数是public权限供我们所调用。那么Optional的本质就是内部储存了一个真实的值在构造的时候就直接判断其值是否为空。那么**of(T value)**的源码如下publicstaticTOptionalTof(Tvalue){returnnewOptional(value);}也就是说of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:通过of(T value)函数所构造出的Optional对象当Value值为空时依然会报NullPointerException。 通过of(T value)函数所构造出的Optional对象当Value值不为空时能正常构造Optional对象。除此之外呢Optional类内部还维护一个value为null的对象大概就是长下面这样的publicfinalclassOptionalT{//省略....privatestaticfinalOptional?EMPTYnewOptional();privateOptional(){this.valuenull;}//省略...publicstaticTOptionalTempty(){SuppressWarnings(unchecked)OptionalTt(OptionalT)EMPTY;returnt;}}那么empty的作用就是返回EMPTY对象。好了铺垫了这么多可以说ofNullable(T value)的作用了上源码publicstaticTOptionalTofNullable(Tvalue){returnvaluenull?empty():of(value);}好吧大家应该都看得懂什么意思了。相比较of(T value)的区别就是当value值为null时of(T value)会报NullPointerException异常ofNullable(T value)不会throw ExceptionofNullable(T value)直接返回一个EMPTY对象。那是不是意味着我们在项目中只用ofNullable函数而不用of函数呢?不是的一个东西存在那么自然有存在的价值。当我们在运行过程中不想隐藏NullPointerException。而是要立即报告这种情况下就用Of函数。但是不得不承认这样的场景真的很少。博主也仅在写junit测试用例中用到过此函数。3.2 orElse(T other)orElseGet(Supplier? extends T other)和orElseThrow(Supplier? extends X exceptionSupplier)这三个函数放一组进行记忆都是在构造函数传入的value值为null时进行调用的。orElse和orElseGet的用法如下所示相当于value值为null时给予一个默认值:Testpublicvoidtest(){Userusernull;userOptional.ofNullable(user).orElse(createUser());userOptional.ofNullable(user).orElseGet(()-createUser());}publicUsercreateUser(){UserusernewUser();user.setName(zhangsan);returnuser;}这两个函数的区别当user值不为null时orElse函数依然会执行createUser()方法而orElseGet函数并不会执行createUser()方法大家可自行测试。至于orElseThrow就是value值为null时,直接抛一个异常出去用法如下所示Userusernull;Optional.ofNullable(user).orElseThrow(()-newException(用户不存在));3.3 map(Function? super T, ? extends U mapper)和flatMap(Function? super T, Optional mapper)这两个函数放在一组记忆这两个函数做的是转换值的操作。publicfinalclassOptionalT{//省略....publicUOptionalUmap(Function?superT,?extendsUmapper){Objects.requireNonNull(mapper);if(!isPresent())returnempty();else{returnOptional.ofNullable(mapper.apply(value));}}//省略...publicUOptionalUflatMap(Function?superT,OptionalUmapper){Objects.requireNonNull(mapper);if(!isPresent())returnempty();else{returnObjects.requireNonNull(mapper.apply(value));}}}这两个函数在函数体上没什么区别。唯一区别的就是入参map函数所接受的入参类型为Function? super T, ? extends U而flapMap的入参类型为Function? super T, Optional。在具体用法上对于map而言如果User结构是下面这样的publicclassUser{privateStringname;publicStringgetName(){returnname;}}这时候取name的写法如下所示StringcityOptional.ofNullable(user).map(u-u.getName()).get();对于flatMap而言:如果User结构是下面这样的publicclassUser{privateStringname;publicOptionalStringgetName(){returnOptional.ofNullable(name);}}这时候取name的写法如下所示StringcityOptional.ofNullable(user).flatMap(u-u.getName()).get();3.4 isPresent()和ifPresent(Consumer? super T consumer)这两个函数放在一起记忆isPresent即判断value值是否为空而ifPresent就是在value值不为空时做一些操作。这两个函数的源码如下publicfinalclassOptionalT{//省略....publicbooleanisPresent(){returnvalue!null;}//省略...publicvoidifPresent(Consumer?superTconsumer){if(value!null)consumer.accept(value);}}需要额外说明的是大家千万不要把if(user!null){// TODO: do something}给写成UseruserOptional.ofNullable(user);if(Optional.isPresent()){// TODO: do something}因为这样写代码结构依然丑陋。博主会在后面给出正确写法至于ifPresent(Consumer? super T consumer)用法也很简单如下所示Optional.ofNullable(user).ifPresent(u-{// TODO: do something});3.5 filter(Predicate? super T predicate)publicfinalclassOptionalT{//省略....Objects.requireNonNull(predicate);if(!isPresent())returnthis;elsereturnpredicate.test(value)?this:empty();}filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤如果包含的值满足条件那么还是返回这个 Optional否则返回 Optional.empty。OptionalUseruser1Optional.ofNullable(user).filter(u-u.getName().length()6);如上所示如果user的name的长度是小于6的则返回。如果是大于6的则返回一个EMPTY对象。四、实战使用4.1 例1在函数方法中以前写法publicStringgetCity(Useruser)throwsException{if(user!null){if(user.getAddress()!null){Addressaddressuser.getAddress();if(address.getCity()!null){returnaddress.getCity();}}}thrownewExcpetion(取值错误);}JAVA8写法publicStringgetCity(Useruser)throwsException{returnOptional.ofNullable(user).map(u-u.getAddress()).map(a-a.getCity()).orElseThrow(()-newException(取指错误));}4.2 例2比如在主程序中以前写法if(user!null){dosomething(user);}JAVA8写法Optional.ofNullable(user).ifPresent(u-{dosomething(u);});4.3 例3以前写法publicUsergetUser(Useruser)throwsException{if(user!null){Stringnameuser.getName();if(zhangsan.equals(name)){returnuser;}}else{usernewUser();user.setName(zhangsan);returnuser;}}JAVA8写法publicUsergetUser(Useruser){returnOptional.ofNullable(user).filter(u-zhangsan.equals(u.getName())).orElseGet(()-{Useruser1newUser();user1.setName(zhangsan);returnuser1;});}

相关推荐

企业微信二次开发实战:如何保存会话上下文,让连续咨询能够正确关联
企业微信二次开发实战:如何保存会话上下文,让连续咨询能够正确关联

在企微机器人的实际业务交互中,客户绝不会像调用 API 那样一次性把所有参数传齐。最真实的场景往往是碎片化的多轮对话:客户先发一句“我要查物流”,机器人问“请输入您的单号”,客户紧接着回复一串数字“SF123456”。 由于 HTTP… · 2026/11/5 3:41:16

Virtual-Display-Driver:在 Windows 10/11 上免费添加虚拟显示器,免硬件扩展桌面
Virtual-Display-Driver:在 Windows 10/11 上免费添加虚拟显示器,免硬件扩展桌面

Virtual-Display-Driver:在 Windows 10/11 上免费添加虚拟显示器,免硬件扩展桌面 【免费下载链接】Virtual-Display-Driver Add virtual monitors to your windows 10/11 device! Works with VR, OBS, Sunshine, and/or any desktop sharing software. … · 2026/11/5 3:41:16

TGRS 2026 即插即用 | 注意力篇 | SMCB:每个像素拥有专属卷积核!全局语义引导,生成逐像素动态卷积
TGRS 2026 即插即用 | 注意力篇 | SMCB:每个像素拥有专属卷积核!全局语义引导,生成逐像素动态卷积

文章目录 模块出处 模块介绍 模块提出的动机(Motivation) 适用范围与模块效果 模块代码及使用方式 模块出处 Paper:Semantic-Guided Fusion Network for Multi-source Remote Sensing Image Classification Code:https://github.com/oucailab/SGFNet 模块介绍 模型整体架… · 2026/11/5 3:41:16

Android双开翻书效果实现:几何模型、触摸状态机与性能优化
Android双开翻书效果实现:几何模型、触摸状态机与性能优化

简介:这份资源面向Android开发者,尤其是希望在电子书或多媒体应用中实现逼真翻页交互的中高级开发者,聚焦「双开」形态的翻书效果,即同时呈现相邻两页并模拟真实书页卷曲过渡。包内共63个文件,以22个class与7个java源码… · 2026/11/5 4:43:54

容器镜像仓库:架构解析与生产实践指南
容器镜像仓库:架构解析与生产实践指南

1. 镜像仓库:容器生态的基石作为一名长期奋战在容器化一线的工程师,我深刻体会到镜像仓库的重要性。如果把容器比作现代软件交付的"集装箱",那么镜像仓库就是确保这些集装箱高效流通的"港口系统"。没有稳定可靠的镜像仓库… · 2026/11/5 4:43:54

中文语音输入技术:深度学习与多模态优化实践
中文语音输入技术:深度学习与多模态优化实践

1. 中文语音输入的现状与痛点作为一个每天要处理大量文字工作的内容创作者,我使用过市面上几乎所有主流的中文语音输入工具。从早期的讯飞输入法到后来的百度语音、搜狗听写,再到现在的微信语音转文字功能,每次切换工具都带着"这次应该能… · 2026/11/5 4:43:54

PPT组合按钮灰色无法组合?一文讲透原因与六步排查解法
PPT组合按钮灰色无法组合?一文讲透原因与六步排查解法

做PPT的人大概都遇到过这种让人抓狂的瞬间:辛辛苦苦把几张图片、几个文本框、一个形状箭头摆成了自己满意的版式,框选之后右键,结果“组合”那一项是灰的,点不动。你以为是软件卡了,重启一遍,还是灰的&… · 2026/11/5 4:43:54

STM32F103C8T6与OpenMV物料搬运机器人:视觉坐标解算与运动控制实战
STM32F103C8T6与OpenMV物料搬运机器人:视觉坐标解算与运动控制实战

简介:这份资源面向参加工程训练类竞赛的学生与嵌入式初学者,提供一套基于OpenMV视觉模块与STM32F103C8T6微控制器的物料搬运机器人完整代码方案,用C语言实现图像识别、目标定位与运动控制的协同,解决机器人自主识别物料并完成抓取… · 2026/11/5 4:43:54

数据湖存储架构与性能优化实战指南
数据湖存储架构与性能优化实战指南

1. 数据湖存储架构深度解析数据湖作为大数据领域的核心基础设施,其存储架构与传统数据仓库有着本质区别。我曾在金融和电商行业主导过多个PB级数据湖建设项目,发现最关键的差异在于数据湖采用"先存储后处理"的范式。这种设计允许我们以原始格式… · 2026/11/5 4:42:54

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

多智能体协作系统架构设计与实践优化
多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39

大模型系统性入门实战指南:从原理到部署微调的全链路路线
大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39

鸿蒙文件系统沙箱机制解析与开发实践
鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码