点击关注公众号,Java干货及时送达


(相关资料图)

文章源:https://blog.csdn.net/zjhred/article/details/84976734

目录

引言

API介绍

实战使用

引言

在文章的开头,先说下NPE问题,NPE问题就是,我们在开发中经常碰到的NullPointerException.假设我们有两个类,他们的UML类图如下图所示

在这种情况下,有如下代码

user.getAddress().getProvince();

这种写法,在user为null时,是有可能报NullPointerException异常的。为了解决这个问题,于是采用下面的写法

if(user!=null){Addressaddress=user.getAddress();if(address!=null){Stringprovince=address.getProvince();}}

这种写法是比较丑陋的,为了避免上述丑陋的写法,让丑陋的设计变得优雅。JAVA8提供了Optional类来优化这种写法,接下来的正文部分进行详细说明

API介绍

先介绍一下API,与其他文章不同的是,本文采取类比的方式来讲,同时结合源码。而不像其他文章一样,一个个API罗列出来,让人找不到重点。

1、Optional(T value),empty(),of(T value),ofNullable(T value)

这四个函数之间具有相关性,因此放在一组进行记忆。

先说明一下,Optional(T value),即构造函数,它是private权限的,不能由外部调用的。其余三个函数是public权限,供我们所调用。那么,Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。好吧,这么说还是比较抽象。直接上Optional(T value)构造函数的源码,如下图所示

那么,of(T value)的源码如下

publicstaticOptionalof(Tvalue){returnnewOptional<>(value);}

也就是说of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:

通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。

通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。

除此之外呢,Optional类内部还维护一个value为null的对象,大概就是长下面这样的

publicfinalclassOptional{//省略....privatestaticfinalOptionalEMPTY=newOptional<>();privateOptional(){this.value=null;}//省略...publicstaticOptionalempty(){@SuppressWarnings("unchecked")Optionalt=(Optional)EMPTY;returnt;}}

那么,empty()的作用就是返回EMPTY对象。

好了铺垫了这么多,可以说ofNullable(T value)的作用了,上源码

publicstaticOptionalofNullable(Tvalue){returnvalue==null?empty():of(value);}

好吧,大家应该都看得懂什么意思了。相比较of(T value)的区别就是,当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。

那是不是意味着,我们在项目中只用ofNullable函数而不用of函数呢?

不是的,一个东西存在那么自然有存在的价值。当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。但是不得不承认,这样的场景真的很少。博主也仅在写junit测试用例中用到过此函数。

2、orElse(T other),orElseGet(Supplier other)和orElseThrow(Supplier exceptionSupplier)

这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。orElse和orElseGet的用法如下所示,相当于value值为null时,给予一个默认值:

@Testpublicvoidtest(){Useruser=null;user=Optional.ofNullable(user).orElse(createUser());user=Optional.ofNullable(user).orElseGet(()->createUser());}publicUsercreateUser(){Useruser=newUser();user.setName("zhangsan");returnuser;}

这两个函数的区别:当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法,大家可自行测试。

至于orElseThrow,就是value值为null时,直接抛一个异常出去,用法如下所示

Useruser=null;Optional.ofNullable(user).orElseThrow(()->newException("用户不存在"));

3、map(Function mapper)和flatMap(Function> mapper)

这两个函数放在一组记忆,这两个函数做的是转换值的操作。

直接上源码

publicfinalclassOptional{//省略....publicOptionalmap(Functionmapper){Objects.requireNonNull(mapper);if(!isPresent())returnempty();else{returnOptional.ofNullable(mapper.apply(value));}}//省略...publicOptionalflatMap(Function>mapper){Objects.requireNonNull(mapper);if(!isPresent())returnempty();else{returnObjects.requireNonNull(mapper.apply(value));}}}

这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Function,而flapMap的入参类型为Function>。

在具体用法上,对于map而言:

如果User结构是下面这样的

publicclassUser{privateStringname;publicStringgetName(){returnname;}}

这时候取name的写法如下所示

Stringcity=Optional.ofNullable(user).map(u->u.getName()).get();

对于flatMap而言:

如果User结构是下面这样的

publicclassUser{privateStringname;publicOptionalgetName(){returnOptional.ofNullable(name);}}

这时候取name的写法如下所示

Stringcity=Optional.ofNullable(user).flatMap(u->u.getName()).get();

4、isPresent()和ifPresent(Consumer consumer)

这两个函数放在一起记忆,isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。这两个函数的源码如下

publicfinalclassOptional{//省略....publicbooleanisPresent(){returnvalue!=null;}//省略...publicvoidifPresent(Consumerconsumer){if(value!=null)consumer.accept(value);}}

需要额外说明的是,大家千万不要把

if(user!=null){//TODO:dosomething}

给写成

Useruser=Optional.ofNullable(user);if(Optional.isPresent()){//TODO:dosomething}

因为这样写,代码结构依然丑陋。博主会在后面给出正确写法

至于ifPresent(Consumer consumer),用法也很简单,如下所示

Optional.ofNullable(user).ifPresent(u->{//TODO:dosomething});

5、filter(Predicate predicate)

不多说,直接上源码

publicfinalclassOptional{//省略....Objects.requireNonNull(predicate);if(!isPresent())returnthis;elsereturnpredicate.test(value)?this:empty();}

filter 方法接受一个Predicate来对Optional中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回Optional.empty。

用法如下

Optionaluser1=Optional.ofNullable(user).filter(u->u.getName().length()<6);

如上所示,如果user的name的长度是小于6的,则返回。如果是大于6的,则返回一个EMPTY对象。

实战使用

例一

在函数方法中

以前写法

publicStringgetCity(Useruser)throwsException{if(user!=null){if(user.getAddress()!=null){Addressaddress=user.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("取指错误"));}

例二

比如,在主程序中

以前写法

if(user!=null){dosomething(user);}

JAVA8写法

Optional.ofNullable(user).ifPresent(u->{dosomething(u);});

例三

以前写法

publicUsergetUser(Useruser)throwsException{if(user!=null){Stringname=user.getName();if("zhangsan".equals(name)){returnuser;}}else{user=newUser();user.setName("zhangsan");returnuser;}}

java8写法

publicUsergetUser(Useruser){returnOptional.ofNullable(user).filter(u->"zhangsan".equals(u.getName())).orElseGet(()->{Useruser1=newUser();user1.setName("zhangsan");returnuser1;});}

其他的例子,不一一列举了。不过采用这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。

推荐内容

  • Optional 是个好东西,你真的会用么?
    Optional 是个好东西,你真的会用么?

  • 每日看点!2023年上半年滇池已处理富藻水1404万立方米
    每日看点!2023年上半年滇池已处理富藻水1404万立方米

  • 当前快报:法国首试高超音速滑翔载具,想挤进“高超音速武器俱乐部”
    当前快报:法国首试高超音速滑翔载具,想挤进“高超音速武器俱乐部”

  • 快看点丨早安,地球村丨国家将新增一节日,拟定在8月
    快看点丨早安,地球村丨国家将新增一节日,拟定在8月

  • 全球今热点:谢依霖张蓝心演的电影 谢依霖整顿npc职场 基本情况讲解
    全球今热点:谢依霖张蓝心演的电影 谢依霖整顿npc职场 基本情况讲解

  • 俞敏洪直播间修改遗嘱:要捐钱给西湖大学
    俞敏洪直播间修改遗嘱:要捐钱给西湖大学

  • 热议:浙江省温州市2023-06-21 08:45发布暴雨蓝色预警
    热议:浙江省温州市2023-06-21 08:45发布暴雨蓝色预警

  • wps合并pdf文件的方法_wps合并pdf|快资讯
    wps合并pdf文件的方法_wps合并pdf|快资讯

  • 四川考生王俊凯高考699分:数学满分 天天动态
    四川考生王俊凯高考699分:数学满分 天天动态

  • 今日热讯:奥特曼一起来找茬好玩吗 奥特曼一起来找茬玩法简介
    今日热讯:奥特曼一起来找茬好玩吗 奥特曼一起来找茬玩法简介

  • 环球快讯:川藏智慧旅游工程四川省高等学校工程研究中心
    环球快讯:川藏智慧旅游工程四川省高等学校工程研究中心

  • 世界热文:亚太实业:筹划公司控制权变更事项 股票延期复牌
    世界热文:亚太实业:筹划公司控制权变更事项 股票延期复牌

  • 科伦博泰拟港股集资16亿港元 引入五家基石投资者-全球微速讯
    科伦博泰拟港股集资16亿港元 引入五家基石投资者-全球微速讯

  • 6500万英镑!AC米兰将从切尔西签下27岁国脚
    6500万英镑!AC米兰将从切尔西签下27岁国脚

  • 浪潮软件: 浪潮软件关于获得政府补助的公告
    浪潮软件: 浪潮软件关于获得政府补助的公告

  • iQOO TWS1无线耳机官宣 1200Kbps无损传输 环球快播
    iQOO TWS1无线耳机官宣 1200Kbps无损传输 环球快播

  • 央行上海总部:5月份长三角地区人民币贷款增加4071亿元
    央行上海总部:5月份长三角地区人民币贷款增加4071亿元

  • 德州乐陵:最美志愿者“舞”出文明风采 焦点短讯
    德州乐陵:最美志愿者“舞”出文明风采 焦点短讯

  • 当前最新:“互联网+”助力增城仙进奉出村进城提速
    当前最新:“互联网+”助力增城仙进奉出村进城提速

  • 2023年6月28日上海市异辛酸价格最新行情预测
    2023年6月28日上海市异辛酸价格最新行情预测

  • 共话中国经济新机遇丨通讯:中国水稻,中国在非洲的亮丽名片-天天热头条
    共话中国经济新机遇丨通讯:中国水稻,中国在非洲的亮丽名片-天天热头条

  • 业绩大幅改善 露笑科技股价涨停|世界速递
    业绩大幅改善 露笑科技股价涨停|世界速递

  • 全球播报:2023年昆明市职业技能竞赛暨小儿推拿竞赛进入决赛阶段
    全球播报:2023年昆明市职业技能竞赛暨小儿推拿竞赛进入决赛阶段

  • 2023年中国500最具价值品牌中免集团再获殊荣   旅游服务行业排名第一
    2023年中国500最具价值品牌中免集团再获殊荣 旅游服务行业排名第一

  • 6月广州二手住宅网签8292宗 同比增长6.58% 每日头条
    6月广州二手住宅网签8292宗 同比增长6.58% 每日头条

  • 今日热闻!南财话你知丨罕见高温来袭 避暑旅游经济正当时;楼市松绑“双限” 更多城市“等风来”
    今日热闻!南财话你知丨罕见高温来袭 避暑旅游经济正当时;楼市松绑“双限” 更多城市“等风来”

  • 当前快讯:热炸了!A股这些板块逆势拉升 啤酒饮料空调机也起来了
    当前快讯:热炸了!A股这些板块逆势拉升 啤酒饮料空调机也起来了

  • 2023年重庆初中级经济师考试报名入口开通时间_简讯
    2023年重庆初中级经济师考试报名入口开通时间_简讯

  • 黑龙江省成人高考招生考试信息港
    黑龙江省成人高考招生考试信息港

  • 中科环保:6月27日融资买入705.66万元,融资融券余额1.09亿元
    中科环保:6月27日融资买入705.66万元,融资融券余额1.09亿元

  • 多国积极探索低碳农业之路(国际视点)-世界快报
    多国积极探索低碳农业之路(国际视点)-世界快报

  • 茄子能与哪种蔬菜种在一起?
    茄子能与哪种蔬菜种在一起?

  • 迷你杜宾犬和小鹿犬区别_迷你杜宾犬怎么养
    迷你杜宾犬和小鹿犬区别_迷你杜宾犬怎么养

  • 三星Galaxy S23首批升级,One UI 6.0具体推送时间曝光
    三星Galaxy S23首批升级,One UI 6.0具体推送时间曝光

  • 电广传媒6月28日盘中跌幅达5%|当前消息
    电广传媒6月28日盘中跌幅达5%|当前消息

  • 合兴船业建造51000吨散货船“明熙炜业”号顺利下水-全球信息
    合兴船业建造51000吨散货船“明熙炜业”号顺利下水-全球信息

  • 世界热讯:互加“白名单”,日韩这个矛盾“告一段落”
    世界热讯:互加“白名单”,日韩这个矛盾“告一段落”

  • 快播:以数字经济为契机提升现代化建设水平
    快播:以数字经济为契机提升现代化建设水平

  • 优雅外观+舒适内饰 2米9轴距尺寸越级 长安启源A07官图发布
    优雅外观+舒适内饰 2米9轴距尺寸越级 长安启源A07官图发布

  • 火耗归公执行了多久_火耗归公
    火耗归公执行了多久_火耗归公

  • 从砌墙到免费开放,“梅里雪山”格局打开了
    从砌墙到免费开放,“梅里雪山”格局打开了

  • 环球讯息:惠泰医疗(688617):6月27日北向资金减持2.27万股
    环球讯息:惠泰医疗(688617):6月27日北向资金减持2.27万股

  • 用这两个“观想”,化解所有问题
    用这两个“观想”,化解所有问题

  • Google Nest Hub Max智能显示启动日期泄漏
    Google Nest Hub Max智能显示启动日期泄漏

  • 汉王科技:公司正在自研的基础大模型|世界微速讯
    汉王科技:公司正在自研的基础大模型|世界微速讯

  • 当前资讯!厦门钨业:拟挂牌转让海峡国际社区项目相关合作协议项下合同权利和义务等
    当前资讯!厦门钨业:拟挂牌转让海峡国际社区项目相关合作协议项下合同权利和义务等

  • 城商行一哥“跑不动”了?_天天快播
    城商行一哥“跑不动”了?_天天快播

  • 中证鹏元:将“塞力转债”的信用等级由AA-调低至A
    中证鹏元:将“塞力转债”的信用等级由AA-调低至A

  • 1%的可能性韩剧剧情(1%的可能性 2003年韩国电视剧)-天天快报
    1%的可能性韩剧剧情(1%的可能性 2003年韩国电视剧)-天天快报

  • 天天热推荐:理想汽车下线40万辆 发布800V高压平台电池
    天天热推荐:理想汽车下线40万辆 发布800V高压平台电池

易居网