应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

还用!null判空?新姿势,值得学习

  引言
  在文章的开头,先说下NPE问题,NPE问题就是,我们在开发中经常碰到的NullPointerException。假设我们有两个类,他们的UML类图如下图所示
  在这种情况下,有如下代码:user。getAddress()。getProvince();
  这种写法,在user为null时,是有可能报NullPointerException异常的。为了解决这个问题,于是采用下面的写法:if(user!null){Addressaddressuser。getAddress();if(address!null){Stringprovinceaddress。getProvince();}}
  这种写法是比较丑陋的,为了避免上述丑陋的写法,让丑陋的设计变得优雅。JAVA8提供了Optional类来优化这种写法,接下来的正文部分进行详细说明
  API介绍
  先介绍一下API,与其他文章不同的是,本文采取类比的方式来讲,同时结合源码。而不像其他文章一样,一个个API罗列出来,让人找不到重点。
  1、Optional(Tvalue),empty(),of(Tvalue),ofNullable(Tvalue)
  这四个函数之间具有相关性,因此放在一组进行记忆。
  先说明一下,Optional(Tvalue),即构造函数,它是private权限的,不能由外部调用的。其余三个函数是public权限,供我们所调用。那么,Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。好吧,这么说还是比较抽象。直接上Optional(Tvalue)构造函数的源码,如下图所示
  那么,of(Tvalue)的源码如下:publicstaticTOptionalTof(Tvalue){returnnewOptional(value);}
  也就是说of(Tvalue)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:通过of(Tvalue)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。通过of(Tvalue)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。
  除此之外呢,Optional类内部还维护一个value为null的对象,大概就是长下面这样的publicfinalclassOptionalT{省略。。。。privatestaticfinalOptionallt;?EMPTYnewOptional();privateOptional(){this。valuenull;}省略。。。publicstaticTOptionalTempty(){SuppressWarnings(unchecked)OptionalTt(OptionalT)EMPTY;returnt;}}
  那么,empty()的作用就是返回EMPTY对象。
  好了铺垫了这么多,可以说ofNullable(Tvalue)的作用了,上源码publicstaticTOptionalTofNullable(Tvalue){returnvaluenull?empty():of(value);}
  好吧,大家应该都看得懂什么意思了。相比较of(Tvalue)的区别就是,当value值为null时,of(Tvalue)会报NullPointerException异常;ofNullable(Tvalue)不会throwException,ofNullable(Tvalue)直接返回一个EMPTY对象。
  那是不是意味着,我们在项目中只用ofNullable函数而不用of函数呢?
  不是的,一个东西存在那么自然有存在的价值。当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。但是不得不承认,这样的场景真的很少。博主也仅在写junit测试用例中用到过此函数。
  2、orElse(Tother),orElseGet(Supplierlt;?extendsTother)和orElseThrow(Supplierlt;?extendsXexceptionSupplier)
  这三个函数放一组进行记忆,都是在构造函数传入的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、map(Functionlt;?superT,?extendsUmapper)和flatMap(Functionlt;?superT,Optionalmapper)
  这两个函数放在一组记忆,这两个函数做的是转换值的操作。
  直接上源码publicfinalclassOptionalT{省略。。。。publicUOptionalUmap(Functionlt;?superT,?extendsUmapper){Objects。requireNonNull(mapper);if(!isPresent())returnempty();else{returnOptional。ofNullable(mapper。apply(value));}}省略。。。publicUOptionalUflatMap(Functionlt;?superT,OptionalUmapper){Objects。requireNonNull(mapper);if(!isPresent())returnempty();else{returnObjects。requireNonNull(mapper。apply(value));}}}
  这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Functionlt;?superT,?extendsU,而flapMap的入参类型为Functionlt;?superT,Optional。
  在具体用法上,对于map而言:
  如果User结构是下面这样的publicclassUser{privateStringname;publicStringgetName(){returnname;}}
  这时候取name的写法如下所示StringcityOptional。ofNullable(user)。map(uu。getName())。get();
  对于flatMap而言:
  如果User结构是下面这样的publicclassUser{privateStringname;publicOptionalStringgetName(){returnOptional。ofNullable(name);}}
  这时候取name的写法如下所示StringcityOptional。ofNullable(user)。flatMap(uu。getName())。get();
  4、isPresent()和ifPresent(Consumerlt;?superTconsumer)
  这两个函数放在一起记忆,isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。这两个函数的源码如下publicfinalclassOptionalT{省略。。。。publicbooleanisPresent(){returnvalue!null;}省略。。。publicvoidifPresent(Consumerlt;?superTconsumer){if(value!null)consumer。accept(value);}}
  需要额外说明的是,大家千万不要把if(user!null){TODO:dosomething}
  给写成UseruserOptional。ofNullable(user);if(Optional。isPresent()){TODO:dosomething}
  因为这样写,代码结构依然丑陋。博主会在后面给出正确写法至于ifPresent(Consumerlt;?superTconsumer),用法也很简单,如下所示Optional。ofNullable(user)。ifPresent(u{TODO:dosomething});
  5、filter(Predicatelt;?superTpredicate)
  不多说,直接上源码publicfinalclassOptionalT{省略。。。。Objects。requireNonNull(predicate);if(!isPresent())returnthis;elsereturnpredicate。test(value)?this:empty();}
  filter方法接受一个Predicate来对Optional中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个Optional;否则返回Optional。empty。
  用法如下OptionalUseruser1Optional。ofNullable(user)。filter(uu。getName()。length()6);
  如上所示,如果user的name的长度是小于6的,则返回。如果是大于6的,则返回一个EMPTY对象。
  实战使用
  例一
  在函数方法中
  以前写法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(uu。getAddress())。map(aa。getCity())。orElseThrow(()newException(取指错误));}
  例二
  比如,在主程序中
  以前写法if(user!null){dosomething(user);}
  JAVA8写法Optional。ofNullable(user)。ifPresent(u{dosomething(u);});
  例三
  以前写法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(uzhangsan。equals(u。getName()))。orElseGet((){Useruser1newUser();user1。setName(zhangsan);returnuser1;});}
  其他的例子,不一一列举了。不过采用这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。
  来源:blog。csdn。netzjhredarticledetails84976734

81101!深圳队爆出冷门,周鹏6中0,对方本土核心三分1110月17日19点35分,CBA常规赛,北控队挑战深圳队。开局之后,双方分差没有拉开。高登凭借着出色的表现,带动球队,建立优势。容子峰传球到正面,三分命中。哈斯2罚中1,廖三宁……戏水大巡游帐篷露营世界公园开启消夏模式北京日报客户端记者孙颖通讯员赵彤7200平方米的戏水乐园,融合美食、音乐、体育的露营活动,沙滩泳池幕布电影这个周末,世界公园开启了消夏模式。随着中小学生暑假的来临,……中国女排重新起航!21人名单出炉,蔡斌新模式将掀起一场青春风中国女排在东京奥运会创造了历史最差战绩,之后郎平辞职,朱婷、张常宁因伤退出,颜妮等人又因为年龄退役,使得中国女排陷入了谷底。不过随着老帅蔡斌重新拿起主教练的教鞭,中国女排又一次……LPL新赛季战队名单曝光,iG被评究极摆烂,三支战队获S级评随着S11赛季即将落幕,备受瞩目的2021英雄联盟LPL冬季转会期也已经在今日(12月13日)晚上7点59分彻底关闭。这意味着除了自由人以外,其他尚处在合同期内的选手都无法再进……温体效应为什么人体的温度在36。7度左右,而在夏季太阳光照射下的气温通常是22度到36度之间,人体为什么会觉得很热,甚至受不了比人体少了几度甚至是十几度的气温。按理来说,人的体温……来石景山西部这座森林公园,换个角度领略京西之美!在热闹喧嚣的城市中带您走进一个有氧呼吸的好去处!石景山区炮山城市森林公园坐落在石景山五里坨地区的炮山城市森林公园置身其中仿佛忘了周边钢筋水泥……想控糖的年轻人你真的了解代糖吗?时下,年轻人的一些不健康的生活习惯,例如熬夜刷剧、常喝奶茶、喜食油腻、久坐不动、不爱运动等,让糖尿病、高血压、癌症等既往老年群体高发的疾病正在不知不觉地盯上他们。为了不让……新赛季谁将是东部最强三巨头?看完西部的三人组真是默默为东部捏一把汗,相比西部的星光璀璨,东部就有点星光暗淡了,不过有几支球队经过休赛季的引援,也表现出极强的竞争力,今天我们就一起来盘点一下凯尔特人塔图姆布……实力即正义!7000万像素分辨率造就的人文镜头岩石星40mm岩石星40mmF5。6,一个擅长于人文故事的全能型镜头。它的颜值精致且典雅,有着高达7000万的像素分辨率,近乎于完美的畸变控制,它是简朴便携的摄影装备的代表之一。……定了,又有三款限定皮肤即将返场,最后一次返场,玄武志不要错过大家好,我是王者老叔,因为夏日盛典主题活动,最近王者峡谷不可谓不热闹,夏日之旅第一站不仅上线了马可波罗,后裔等多款高级皮肤,还有免费送皮肤的活动。现在夏日之旅到达了第二站,官方……最早的游山玩水,您可要悠着点儿千里万里游山玩水之感,我还一字未写,没有这第一次的破冰,写到哪里总感觉是无源之水。在报纸杂志上从未出现过旅游二字的年代,用亲情,友情加大二八车,组织了第一次两日游山。……美媒詹姆斯差1326分问鼎NBA历史得分王下赛季多少场能达成直播吧7月26日讯目前詹姆斯生涯常规赛总得分为37062分,而NBA历史得分王贾巴尔生涯总得分为38387分,詹姆斯距离成为NBA历史得分王还差1326分。美媒发问:……
终于知道为什么叫云台山了!云海真的绝青山相伴,云海缭绕,蔚为壮观国庆假期,云台山云海奇观持续上线穿云而过,索道直达;站在山顶,风起云涌此刻的云台山处处是仙境,一起出发吧!茱萸峰、凤凰岭双条……队记火箭管理层对上赛季球队年轻人的成长感到满意,持续期待北京时间8月17日,根据NBA火箭记者KellyIko报道关于管理层对于上个赛季火箭队整体表现的评价,球队管理层认为主教练塞拉斯和上赛季球队中年轻人的成长表现是让所有人感到满意……10场8胜冲亚冠,日本内战8强,伊涅斯塔不服输,大败领头羊有明晚7点,神户胜利船将重返亚冠赛场,争夺亚冠8强的席位。首先,他们将与同胞横滨水手进行16强赛,对手是日本J联赛冠军种子,接下来的7天内,他们将完成淘汰赛,不久他们就会知道是否……光伏钠离子电池机器人储能新能源车华为智能电网光伏钠离子电池机器人储能新能源车华为智能电网!公司参与打造全球首个1MWh钠离子电池光伏储能系统,且参股公司钠离子电池产业化时间领先宁德时代,分析师预计2025年钠电池营收48……陈皮泡茶可以健脾开胃,为何新鲜的橘子皮泡茶,却对人体有害呢?今天科普知识的开头,先给大家讲一个故事:在北宋时期的有个著名诗人,曾经写出:先天下之忧而忧,后天下之乐而乐的名句,大诗人范仲淹曾经在东台任职时,他母亲身体不太健康,但是又不愿意……美媒Meta将于当地时间周三开始大规模裁员,扎克伯格称要为公彭博11月8日消息,知情人士透露,Facebook母公司MetaPlatforms计划当地时间周三开始广泛裁员,这是在利润令人失望且收入下降后该公司削减成本计划的一部分。……开源免费截图软件ShareX如何改变文字水印和logo特效透达芬奇之前和大家分享过开源免费截图软件ShareX,ShareX不仅可以含鼠标截图,同时还可实现对截图实时自动添加文字水印和logo,如下图所示,但是达芬奇在使用过程中发现,当……什么样的生活方式才是你真正需要的?不知什么时候开始秋天的第一杯奶茶成为众多年轻人打卡朋友圈的一种风潮生活要有仪式感奶茶好像成为仪式感的标配然而,因为长期喝奶茶进医院的新闻屡屡出现越……4。39亿年前的牙齿化石颠覆了人们长期以来对进化的看法罕见的中国化石牙齿改变了科学家对脊椎动物进化的信念。一个国际科学家团队发现了可以追溯到4。39亿年前的有齿鱼遗骸,这表明现代软骨鱼类和骨鱼类的祖先比以前认为的要早得多。这……千万别一个人爬武功山千万别一个人爬武功山不然你跟我一样暑假放假直奔武功山,一个人,背着22斤的书包,杭州到江西,火车十小时。虽然过程有点狼狈,但真的很自由暑假的时候武功山是有学生……国庆小长假正确的打开小方法,你喜欢哪个?许多人翘首以盼的国庆七天小长假如期而至!对于家长和孩子字来说,这七天更是难得的亲子共度时光。但是,假期陪孩子做什么,还真是让不少家长头疼。出去旅游,人山人海,宅在家里,孩子也不……冲上热搜!张国伟夺校运会冠军,小学生们疯狂,双手指天庆祝张国伟已经宣布复出,去年他决定重启自己的跳高生涯,期间遭到过质疑,毕竟他现在已经是30多岁的老将了,想要重返巅峰,完成目标的2米40难度极大。到了2022年,张国伟收到海外参赛……
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网