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

告别空指针让代码变优雅,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的话,那么这个问题能够得到避免。
  就像多使用设计模式一样,让自己的代码更加健壮优雅,还是要多使用一些的!当然不能过渡使用!!
  对你有帮助,还请不要吝啬你的发财小手点点关注哈!、
  写作不易,大家给点支持,你的支持是我写作的动力哈!
  关注小编的微信公众号,一起交流学习!文章首发看哦!
中国第一个气候宜居城市,节奏慢,生活悠闲,江浙沪养老首选你知道中国第一个气候宜居城市在哪吗?很多人以为是在云南,因为这里是公认最宜居的地方。其实这座城市在浙江,它就是建德,一座低调安宁又美丽清秀的小城。建德位于杭州,是浙江省辖县级市,人全国500强企业之江苏榜无锡14家苏北地区仅3家,5市零入围企业是推动经济增长提供就业的重要单元,尤其是大型巨型企业甚至可以带动一个行业的发展或一个地区的经济走势。江苏省我国第二经济大省,工业大省之一。在一步步的探索中不仅形成了自己的发展模对全球气候变暖的一点猜想气候变暖应该同磁力磁场变化有关,太阳及太阳系运行的猜想太阳应该是一个巨大的磁力集中和交换体,同时也是太阳系的核心。太阳系其他星体的一切能量都来自于太阳,各个球体一方面在接收太阳能量早资道苹果退出滴滴董事会软银宣布愿景基金CEO辞去集团职务苹果退出滴滴董事会曾投资近70亿元8月31日消息,苹果公司已经放弃了滴滴出行董事会席位,其代表已经离开滴滴董事会。根据滴滴在8月4日宣布的董事会调整新闻稿,苹果企业发展副总裁阿德里秋季开学在即,这3款手机值得考虑哈喽大家好,这里依然是为您简洁播报的流星数码馆,秋季开学在即,很多家长和学生朋友们都在问,到底该买一款什么样的手机更适合自己呢?首先我们要知道,由于疫情原因加上物资消费水平升高,很秋季养生指南知多点秋季,暑夏的高温已降低,人们烦躁的情绪也随之平静,且秋风带来秋季宜人的景色。此时切勿因眼前的美景忽视了养生,许多因素往往在不经意间影响着您的健康,且夏季过多的耗损也应在此时及时补充秋季如何保障品质生活?或许你需要它们终于,炎热的酷暑逐渐离我们而去,秋高气爽的时节到来。在享受凉爽秋风的同时我们也要注意,秋季雨水减少天气干燥,附着在灰尘上的细菌更容易传播,支气管炎哮喘之类的呼吸道疾病也更容易发作。千元机配置不输价格亲民,优缺点告诉你,千元机到底怎么选?各大厂商都在3000这个段位各显神通,但是对于更平价的市场也没有放过,毕竟3000对于类似像学生党或者是刚入职场的新人这样的预算不高的群体,一次拿出3000多也是有些困难,但是在使目前公认的三款零差评手机,价格覆盖低中高三档,闭眼买就行不得不说今年国内手机市场真的是异常激烈,就单说八月份,短短一个月就有十几款新机被发布。其中好多款新机的表现都相当不错,尤其是今天介绍的这三款手机,个个表现出色,市场好评率超高,几乎疯狂小杨哥国货直播,他来了随着互联网事业的迅猛发展,直播带货以势不可挡的姿态成为了带动市场消费的主力军,8月31日晚新华社新媒体中心新华社客户端电商频道携手疯狂小杨哥进行国货专场直播,又将会碰撞出怎样的火花华西证券给予长安汽车买入评级华西证券股份有限公司崔琰,胡惠民近期对长安汽车进行研究并发布了研究报告系列点评七十三新品表现强势金九银十来临,本报告对长安汽车给出买入评级,当前股价为14。11元。长安汽车(000
国产EDA发展寒冬已过,华大九天工具龙头,在国产化大潮中受益(报告出品方分析师平安证券付强闫磊徐勇徐碧云)一公司是国内EDA工具龙头,正在国产化大潮中受益1。1公司坚守EDA赛道,是国产化替代的中坚力量EDA是ElectronicDesig纯玩纯开一整天,我们玩透了宏光MINIEV敞篷版的奥秘前段时间,唯电新能源汽车社区前往柳州参加五菱活动,小体验了一把网红神车宏光MINIEV敞篷版,本以为只能做一期简易体验报告,没想到受深圳静默的影响,继续在柳州多待了一天,恰好获得了一年不见,人工智能又长了新本事本报记者徐晶卉张天弛从识别甲骨文到辨认难度系数更高的钟鼎文,写诗作画的艺术修养也大大提高网络诈骗陷阱面前,反诈盲盒层层解套更加聪明2022世界人工智能大会今天拉开帷幕,让我们一起来43英寸巨屏4。3s破百华为加持!飞凡R7卷疯了,蔚来ES7扛得住?太平洋汽车网评测频道43英寸三联屏1颗激光雷达2颗4D成像雷达全车搭载33个高性能感知硬件华为视觉增强ARHUD平视系统英伟达超算力芯片轴距2950mm当这些点汇聚到同一台车上时,宝马集团董事长齐普策继续扩大在华投资,加强跨国合作共谋发展过去十年中,中国建立了强大的可持续的技术产业基础,无论是太阳能风能动力电池还是新能源汽车,中国不单单在市场容量方面处于领先地位,更是引领全球的创新。中国经营报记者获悉,宝马集团董事筑牢工业互联网安全屏障在工业数字化网络化智能化转型需求带动下,以泛在互联全面感知智能优化安全稳固为特征的工业互联网不断发展壮大。随着与制造业加快融合,新一代信息技术在产业链供应链上下游不断延伸,网络和数为什么2022年下半年的手机,降价越来越快了?总体来看今年下半年的手机降价速度是越来越快了,上半年发布的手机降幅都在500左右,而在二级市场当中出手的价格往往会更低,那究竟是什么原因导致下半年的手机降价越来越快了呢??原因一大目前三款厉害的国产手机,性能顶级价格良心,还买什么苹果14?今天要和大家三款性能顶尖且价格优秀的国产手机,预算不高的朋友可以不用凑iPhone14的热闹,直接入手这四款就行。华为P50Pro处理器麒麟9000芯片屏幕6。6英寸,OLED,1天猫国际与水羊国际联手造新,加速引入孵化进口美妆个护新品牌借助跨境电商进口模式,全球美妆个护品牌正加速拓展中国市场。9月1日,天猫国际与水羊国际正式启动联合造新计划,双方将围绕十大进口美妆个护赛道加速引入孵化新品牌,深入全球美妆产业带挖掘央行大幅降准,市场反应平淡,你咋看?当前为稳经济,国家出台各种应对策略。但金融空转,超量发行的货币信贷无法有效流入实体经济。这次央行大幅度下调金融机构外汇存款准备金率。但市场似乎不买账。其实我们的金融业及从业人员深受轮到中国出招了,人民币汇率贬值,对我国带来什么影响?如今在全球各国的共同努力下,我们的地球迎来了长时间的和平,战争对于我们大多数人而言已经十分遥远了,我国新一代更是在和平年代成长起来的。但是战争并不一定都是军事斗争,在当前的世界环境