范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

告别空指针让代码变优雅,Optional使用图文例子源码解读

  一、前言
  我们在开发中最常见的异常就是 NullPointerException  ,防不胜防啊,相信大家肯定被坑过!
  这种基本出现在获取数据库信息中、三方接口,获取的对象为空,再去get出现!
  解决方案当然简单,只需要判断一下,不是空在去后续操作,为空返回!
  所有在JDK8时出现了专门处理的方案,出来很早了,但是小编惭愧一直没有去使用它!
  最近在看《Java开发手册》,一直想着提高自己的代码水平,文中就指出了使用 Optional  来解决NullPointerException  ! 二、Java开发手册规范
  小编使用的是2022版的黄山版,29页写到:
  【推荐】  防止 NPE,是程序员的基本修养,注意 NPE 产生的场景: 返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE
  ==反例==:public int method() { return Integer 对象; },如果为 null,自动解箱抛 NPE。  数据库的查询结果可能为 null。  集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。  远程调用返回对象时,一律要求进行空指针判断,防止 NPE。  对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。  级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
  ==正例==:使用 JDK8 的  Optional   类来防止 NPE 问题。
  这份手册还是不错的,推荐反复阅读,虽然进不去大厂,也要自觉约束自己的代码风格,努力向大厂靠!
  大家现在不知道哪里找的可以下载一下:
  《Java开发手册》:https://github.com/alibaba/p3c  三、Optional常用方法
  小编带大家一起从api文档中的方法,一个个带大家慢慢去了解它!  1. empty()
  返回一个空的Optional实例:Optional.empty   Optional empty = Optional.empty(); log.info("empty值:{}",empty);
  在这里插入图片描述  2. of(T value)
  传入一个参数,返回一个  Optional  对象,如果参数为空,报NullPointerException  ! Test testNew  = new Test(); Test test = null; Optional optionalNew = Optional.of(testNew); log.info(" optional对象:{}",optionalNew); Optional optional = Optional.of(test);
  在这里插入图片描述
  ==源码查看:==
  我们看到参数为空会报NullPointerException  ,我们去方法内部看一下就明白了: public static  Optional of(T value) {     return new Optional<>(value); } private Optional(T value) {     this.value = Objects.requireNonNull(value); } public static  T requireNonNull(T obj) {     if (obj == null)         throw new NullPointerException();     return obj; }
  我们发现是在Objects  类中的requireNonNull  方法中判断了是否为空!
  这个还会出现NullPointerException  ,所以我们一般使用下面的这个方法! 3. ofNullable(T value)
  参数传入一个对象,返回一个Optional对象,如果为空,将返回一个空的Optional对象,就等于Optional.empty   Test testNew  = new Test(); Test test = null; Optional optionalNew = Optional.of(testNew); log.info(" optional对象:{}",optionalNew);  Optional optionalTest = Optional.ofNullable(test); log.info(" optional对象中的ofNullable方法返回值:{}",optionalTest); Optional optionalTestNew = Optional.ofNullable(testNew); log.info(" optional对象中的ofNullable方法new返回值:{}",optionalTestNew);
  在这里插入图片描述
  ==源码查看:==
  我们发现是在方法开始进行非空判断,再去调用上面的of(T value)  方法 public static  Optional ofNullable(T value) {     return value == null ? empty() : of(value); } 4. get()
  如果此Optional中存在值,则返回该值,否则抛出  NoSuchElementException  。 Test testNew  = new Test(); Test test = null; Optional optionalNew = Optional.of(testNew); log.info(" optional对象:{}",optionalNew); // Optional optional = Optional.of(test);  Optional optionalTest = Optional.ofNullable(test); log.info(" optional对象中的ofNullable方法返回值:{}",optionalTest); Optional optionalTestNew = Optional.ofNullable(testNew); log.info(" optional对象中的ofNullable方法new返回值:{}",optionalTestNew);  Test test2 = optionalTestNew.get(); log.info("原来有值的:经过Optional包装后get后得到原来的值:{}",test2); Test test1 = optionalTest.get(); log.info("原来没有值的:经过Optional包装后get后得到原来的值:{}",test1);
  在这里插入图片描述
  ==源码查看:==
  调用开始会进行值判断,如果为空则抛异常! public T get() {     if (value == null) {         throw new NoSuchElementException("No value present");     }     return value; } 5. isPresent()
  如果存在值,则返回true,否则返回false。
  这里代码就不加上面的,大家参考上面的获取一个Optional对象 boolean present = optionalTestNew.isPresent(); log.info("optionalTestNew调用是否为空:{}",present); boolean present1 = optionalTest.isPresent(); log.info("optionalTest调用是否为空:{}",present1);
  在这里插入图片描述
  ==源码查看:==
  这就比较简单了! public boolean isPresent() {    return value != null; } 6. ifPresent(Consumer consumer)
  如果存在值,则使用该值调用指定的使用者,否则不执行任何操作。
  主要的就是入参数一个函数式接口,有值就会去执行,为空则不进行任何操作!
  ==小技巧:==
  开始对lambda不了解时,可以先按照上面这种方式进行写,
  大家可以看到Idea给置灰了,就是可以优化,我们Alt+Enter
  然后再次Enter  就会变成后面的lambda!
  在这里插入图片描述
  optionalTest.ifPresent(  new   Consumer() {
  @Override
  public    void    accept  (Test test)   {
  log.info( "我是调用ifPresent执行后的打印====="  );
  }
  });
  optionalTestNew.ifPresent(testInner -> log.info( "我是调用ifPresent执行后的打印"  ));
  在这里插入图片描述
  ==源码查看:==
  还是先判断不为空才去执行函数式接口! public void ifPresent(Consumer<? super T> consumer) {     if (value != null)         consumer.accept(value); } 7. filter(Predicate predicate)
  如果存在值,并且该值符合规则,则返回描述该值的Optional,否则返回空Optional
  是一个Predicate函数接口,可以传入实现了Predicate接口的lambda表达式!
  如果不符合条件就会返回一个Optional.empty   testNew.setName("萧炎"); testNew.setAge(33); Optional optionalTest1 = optionalTestNew.filter(test1 -> test1.getAge() > 30); log.info("过滤后的结果:{}",optionalTest1.get());
  在这里插入图片描述
  ==源码查看:==
  就是判断一下表达式和值是否为空,然后就是根据规则判断 public Optional filter(Predicate<? super T> predicate) {    Objects.requireNonNull(predicate);     if (!isPresent())         return this;     else         return predicate.test(value) ? this : empty(); } 8. map(Function mapper)
  如果存在值,则将提供的映射函数应用于该值,如果结果为非空,则返回描述结果的Optional。否则,返回空的Optional。
  也是一个函数式接口! Optional stringOptional = optionalTestNew.map(Test::getName); log.info("map后获得字段值:{}",stringOptional.get());
  在这里插入图片描述
  ==源码查看:==
  也是进行非空判断,然后执行lambda得到字段后放到ofNullable方法中! public Optional map(Function<? super T, ? extends U> mapper) {     Objects.requireNonNull(mapper);     if (!isPresent())         return empty();     else {         return Optional.ofNullable(mapper.apply(value));     } } 9. flatMap(Function> mapper)
  如果存在值,则将提供的Optional方位映射函数应用于该值,返回该结果,否则返回空的Optional。此方法类似于map,但提供的映射器的结果已经是可选的,并且如果调用,flatMap不会不会在最后进行任何包装。   Optional optional = optionalTestNew.flatMap(OptionalTest::getFlatMap); log.info("flatMap后得到的字段:{}",optional.get());  private static Optional getFlatMap(Test test){     return Optional.ofNullable(test).map(Test::getName); }
  在这里插入图片描述
  ==源码查看:==
  也是进行非空判断,然后和map不同的是不执行ofNullable方法 public Optional flatMap(Function<? super T, Optional> mapper) {     Objects.requireNonNull(mapper);     if (!isPresent())         return empty();     else {         return Objects.requireNonNull(mapper.apply(value));     } } 10. orElse(T other)
  如果有值则将其返回,否则返回指定的其它值。
  如果你是一个对象,orElse()  也要是相同对象! String message = null; String messageNew = "关注公众号:小王博客基地";  String nullString = Optional.ofNullable(message).orElse("这是一个空字符串!"); log.info("这是空字符串打印的:{}",nullString); String string = Optional.ofNullable(messageNew).orElse("=====这是一个空字符串!"); log.info("这是字符串打印的:{}",string);
  在这里插入图片描述
  ==源码查看:==
  简单的为空返回自己定义的,不为空直接返回! public T orElse(T other) {     return value != null ? value : other; } 11. orElseGet(Supplier other)
  返回值(如果存在),否则调用other并返回该调用的结果。
  区别:
  orElse方法将传入的参数作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值
  ==如果没有复杂操作,Idea也会提醒我们不要使用这个,使用orElse即可!== String message = null; String messageNew = "关注公众号:小王博客基地"; String orElseGet = Optional.ofNullable(message).orElseGet(() -> "这还是一个空的字符串"); log.info("orElseGet调用:这是空字符串打印的:{}",orElseGet); String orElseGetString = Optional.ofNullable(messageNew).orElseGet(() -> "这还是一个空的字符串"); log.info("orElseGet调用:这是字符串打印的:{}",orElseGetString);
  在这里插入图片描述
  ==源码查看:==
  和orElse一样,只不过为空调用lambda执行! public T orElseGet(Supplier<? extends T> other) {     return value != null ? value : other.get(); } 12. orElseThrow(Supplier exceptionSupplier)
  返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。   String message = null; String messageNew = "关注公众号:小王博客基地"; Optional.ofNullable(messageNew).orElseThrow(() -> new RuntimeException("为空了,还不看看!")); Optional.ofNullable(message).orElseThrow(() -> new RuntimeException("为空了,还不看看!"));
  我们可以自定义异常,然后来引用!
  在这里插入图片描述
  ==源码查看:==
  为空则走自己写的异常! public  T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {     if (value != null) {         return value;     } else {         throw exceptionSupplier.get();     } } 13. 例子汇总/**  * @author wangzhenjun  * @date 2023/2/27 10:22  */ @Slf4j public class OptionalTest {      public static void main(String[] args) {          Optional empty = Optional.empty();         log.info("empty值:{}",empty);           Test testNew  = new Test();         Test test = null;         Optional optionalNew = Optional.of(testNew);         log.info(" optional对象:{}",optionalNew); //        Optional optional = Optional.of(test);          Optional optionalTest = Optional.ofNullable(test);         log.info(" optional对象中的ofNullable方法返回值:{}",optionalTest);         Optional optionalTestNew = Optional.ofNullable(testNew);         log.info(" optional对象中的ofNullable方法new返回值:{}",optionalTestNew);          Test test2 = optionalTestNew.get();         log.info("原来有值的:经过Optional包装后get后得到原来的值:{}",test2);         // Test test1 = optionalTest.get();         // log.info("原来没有值的:经过Optional包装后get后得到原来的值:{}",test1);          boolean present = optionalTestNew.isPresent();         log.info("optionalTestNew调用是否为空:{}",present);         boolean present1 = optionalTest.isPresent();         log.info("optionalTest调用是否为空:{}",present1);          optionalTest.ifPresent(new Consumer() {             @Override             public void accept(Test test) {                 log.info("我是调用ifPresent执行后的打印=====");             }         });         optionalTestNew.ifPresent(testInner -> log.info("我是调用ifPresent执行后的打印"));          testNew.setName("萧炎");         testNew.setAge(33);         Optional optionalTest1 = optionalTestNew.filter(test1 -> test1.getAge() > 30);         log.info("过滤后的结果:{}",optionalTest1.get());          Optional stringOptional = optionalTestNew.map(Test::getName);         log.info("map后获得字段值:{}",stringOptional.get());          Optional optional = optionalTestNew.flatMap(OptionalTest::getFlatMap);         log.info("flatMap后得到的字段:{}",optional.get());          String message = null;         String messageNew = "关注公众号:小王博客基地";          String nullString = Optional.ofNullable(message).orElse("这是一个空字符串!");         log.info("这是空字符串打印的:{}",nullString);         String string = Optional.ofNullable(messageNew).orElse("=====这是一个空字符串!");         log.info("这是字符串打印的:{}",string);          String orElseGet = Optional.ofNullable(message).orElseGet(() -> "这还是一个空的字符串");         log.info("orElseGet调用:这是空字符串打印的:{}",orElseGet);         String orElseGetString = Optional.ofNullable(messageNew).orElseGet(() -> "这还是一个空的字符串");         log.info("orElseGet调用:这是字符串打印的:{}",orElseGetString);          Optional.ofNullable(messageNew).orElseThrow(() -> new RuntimeException("为空了,还不看看!"));         Optional.ofNullable(message).orElseThrow(() -> new RuntimeException("为空了,还不看看!"));        }      private static Optional getFlatMap(Test test){         return Optional.ofNullable(test).map(Test::getName);     }  } 四、总结
  这里就不在演示实战了,基本上组合使用:
  Optional.ofNullable(需要判断的对象).ifPresent(具体操作)
  其实和if相比就是显得优雅一些,主要是防止某处没考虑到,忘记if判断,那么后续可能会导致空指针,如果使用Optional的话,那么这个问题能够得到避免。
  就像多使用设计模式一样,让自己的代码更加健壮优雅,还是要多使用一些的!当然不能过渡使用!!
  对你有帮助,还请不要吝啬你的发财小手点点关注哈!、
  写作不易,大家给点支持,你的支持是我写作的动力哈!
  关注小编的微信公众号,一起交流学习!文章首发看哦!
什么是新QLED?它与QLED和OLED有何不同?OLEDQLEDNeoQLED有很多电视技术术语让您想知道这些类型的电视之间有何不同。让我们看看三星的NeoQLED电视与标准QLED型号有何不同。三星改进的量子点显示器NeoQL只要3299元,拯救者Y90电竞手机带你上分带你飞不管是学生党还是上班族,每天学习工作之后,闲下来玩玩游戏总是必需的,而最近全国高温肆虐,只要不是在屋子里呆着就是无死角的蒸烤桑拿,不仅人受不了,手机也受不了。如果顶着高温玩游戏的话中兴Axon40SE真机曝光中兴新机ZTE9047在FCC(美国联邦通讯委员会)认证时被泄露,包括外观图拆解图,以及用户手册。据悉,这款新机将命名为中兴Axon40SE或中兴BladeV40S,取决于售卖地区HarmonyOS3。0及最全升级名单2022年7月27日1930华为新品发布会面向未来,全面进化公布全新HarmonyOS3。0操作系统目前HarmonyOS设备数突破2。4亿,生态设备发货量突破1。5亿新品华为Ma聊一款不到20mm的GeForceRTX3070游戏本还记得Y9000X发布后,我们也尽快做出了一期视频评测感兴趣的同学可以去Bilibili搜索笔吧评测室找到这期详细测评。我们决定做GeForceRTX3060笔记本电脑GPU版本的亚洲杯!你担心的中国男篮最终还是输了亚洲杯中国和黎巴嫩这场比赛在赛前就被很多人认为我们没有把握赢球,曾经的我们什么时候担心过和黎巴嫩的输赢。其实大家都在说这次组队的困难,这是客观原因。主观上来说还是战术层面的问题。一显卡爆仓辉达新品延明年上市显卡爆仓辉达新品延明年上市市场传出,辉达RTX40系列新显卡,部分品项又要延后至明年才问世。(路透)显卡库存爆仓,价格持续修正之际,市场传出,辉达原本已延后至今年下半年推出有性能怪300的英伟达gtx10606g满血版?事情是这样的(以下省略一万字)反正大概就是水群看见群友翻闲鱼翻到了280块钱的不确定能不能点亮的p106,而且上面是带接口的,然后他收回来发现显卡核心长这样的故事我直接一个羡慕群友金匮要略学习笔记5。附方中风历节病脉证治第五附方风引汤除热瘫痫。大黄干姜龙骨各四两桂枝三两甘草牡蛎各二两寒水石滑石赤石脂白石脂紫石英石膏各六两上十二味,杵,粗筛,以韦囊盛之,取三指撮,井花水三升,煮三沸,30!伊藤美诚强势晋级,一脸傲娇,陈梦将与早田希娜争夺4强2022年WTT冠军赛布达佩斯站女单比赛,日本名将伊藤美诚30横扫单晓娜强势晋级女单8强。此役,伊藤美诚没有遭遇太大挑战,单局轰出112,晋级之路比较顺利。全场,伊藤美诚表情严肃,42!中国女足奇迹翻盘超车,韩国队2大将发声有信心复仇中国女足在过去十几年没有太大进步,甚至有不进则退的现象。世界足坛越来越重视女足的发展,不仅仅欧美女足进步神速,亚洲女足也在高速发展,韩日女足逐渐成为了亚洲一流强队,还有朝鲜和澳大利
一身牛仔衣7套不同风格,穿出青春活力感,女生可以帅气又自由周末的轻快心情,就交给一身牛仔装吧,我为大家梳理了关于牛仔服的搭配,希望你的周末能穿得活力又美丽。先为自己选件合适的牛仔夹克,可以是合身款式,可以搭配直筒深色牛仔裤。或是剪裁更加紧冠军背后她力量Flashversion9,0orgreaterisrequiredYouhavenoflashplugininstalledDownloadlatestversionfromhe文化之窗丨大学生为什么组团到淄博吃烧烤?淄博烧烤火了!山东的大学生纷纷在周末坐高铁打卡淄博烧烤,一则大学生组团到淄博吃烧烤的词条登顶同城热搜榜榜首,搜索量超500万。淄博火车站挤满了为一顿烧烤而来的大学生。据淄博火车站数2023年河南荥阳第八届黄河樱花节盛大启幕春有约,花不误,岁岁年年不相负,又到一年赏樱时。3月10日,由河南省文化和旅游厅指导,河南省戏剧家协会河南省文艺志愿者协会河南省杂技家协会河南广播电视台交通事业部郑州市文化广电和旅建设创业社区打造活力首府丨乌鲁木齐市水磨沟区今年打造水磨滨河文化旅游社区水磨沟区今年打造水磨滨河文化旅游社区今年,乌鲁木齐市水磨沟区将利用水磨沟公园和水磨滨河景观带业态效应,打造水磨滨河文化旅游社区,具体将建设烟火巴扎创业市场乐活水磨山夏云集早夜市以及梯田种出旅游饭龙胜大寨村的蝶变之路龙胜大寨村梯田景观国际在线报道(记者郭雅雯)广西桂林市龙胜各族自治县龙脊镇大寨村,地处龙脊梯田核心区金坑片区。这里有着2300多年的梯田耕种历史,村民世代在山坡上开垦水田,形成了气山东必去景点威海(著名景点介绍)威海威海介绍威海位于山东半岛最东端,背靠大陆,三面濒临黄海,西与烟台市接壤,市区面积!408平方公里。威海历史悠久,早在新石器晚期,就有人类在这里生息繁衍。元代这里已成为海上要津明泸州东岩桃花次第,不仅让嬢嬢乐开怀,这一园的春色不要错过在泸州国窖大桥头,原来属于少鹤山的临江山脉,在好多年前,被开发成了新东岩公园。在老东岩摩崖石刻暂时沉寂的日子里,它很好的弥补了泸州古八景东岩夜月的空窗期,经过多年的维护与拓展,早已欢迎来京海市打卡狂飙一剧带热了整个大江门(蓬江市区新会区台山市恩平市),暴增的游客瞬间令这平静的小城变得热闹非常,作为一个在蓬江区生活了几十年的老江门,有点心痛的看着游客乱停的车辆将长堤边的路基都春天为什么要养肝?中医理论中,人体器官与季节一一对应,春天和肝脏同属木,春气通肝,所以春天是养肝的大好时节,肝主疏泄与藏血,所以在春季调肝能够改善肝阳气的生发和输血功能,也能够调节人体脏腑的机能,使甲流中招反复咳嗽咋办?过来人多吃这5样,润肺止咳恢复快最近很多学校,因为甲流陆续停课,甲流虽然不是新冠,但感染症状和新冠病毒非常相似,像发烧咳嗽浑身酸疼等。甲流作为急性呼吸道传染病,最常出现在冬春交替时期。早春气温较低,空气干燥,天气