1.需求分析

调用RPC返回结果、包装类转简单类型,拆箱过程最容易出现NPE问题。JDK8之前需要小心翼翼对各种类型进行判空,可通过JKD8-Optional类来预发未知的NPE错误。

2.关于避免NPE的常识

  • 【强制】所有POJO类属性必须使用包装数据类型
  • 【强制】所有RPC方法的返回和参数必须使用包装数据类型
  • 【推荐】所有局部变量使用基本简单数据类型
  • Ps:
    • POJO类属性没有初值是提醒使用者在需要使用时,必须自己显示地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。
    • 正例:数据库的检查结果可能是null,因为自动拆箱,用基本数据类型接受有NPE风险。
    • 反例:比如显示成交总额涨跌情况,即正负x%,x为基本简单类型,调用RPC服务,调用不成功时,返回的是默认值,页面显示为0%,显然这是不合理的,应该显示成-%。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败、异常推出。
  • 【推荐】防止NPE,是程序员基本修养,注意NPE产生的场景。
    • 1)返回类型为基本简单数据类型,return包装数据类型的对象时,自动拆箱有可能产生NPE。
    • 反例: public int func(){ return Integer对象}; 如果为null,自动拆箱抛出NPE。
    • 2)数据库的查询结果可能为null。
    • 3)集合里的元素即使isNotEmpty,取出的元素仍有可能为null。
    • 4)远程调用返回对象时,一律要求进行空指针判断,防止NPE。
    • 5)对于Session中获取的数据,建议NPE检查,避免空指针。
    • 6)级联调用obj.getA().getB().getC();一连串调用,易产生NPE。
    • 正例:使用JDK8的Optional类防止NPE问题。

3.JDK8-Optinal类防止NPE

JDK8增加了许多有用的API,Optional类就是其中之一。如果不了解Optional类,只是简单的认为它可以解决NPE问题,于是就有了如下代码:
    Optional<User> user = xxxif(user.isPresent){return user.getOrders();}else {return Collections.emptyList();}

上面采用Optional类的代码和我们正常下面写法并没有太大区别:

    User user = xxxif(user!=null){return user.getOrders();}else{return Collections.emptyList();}

两者没有实质的区别,那么Optinal的正确使用姿势来了:

  • 先来了解下Optional常用的方法有哪些?
   1.public<U> Optional<U> map(Function<? super T,? extends U>mapper)2.public T orElse(T other)3.public T orElseGet(Supplier <? extends T> other)4.public void ifPresent(Consumer <? super T> consumer)5.public Optional <T> filter(Predicate <? supper T> predicate)6.public <U> OPtional <U> flatMap(Function <? supper T,Optional <U> mapper>>)7.public <X extends Throwable T> orElseThrow(Supplier <? extends X> exceptionSupplier) throws X
  • Optional的三种构造方法:

    • Optional.of(obj):要求传入obj不能为null,否则还没开始初始化就NPE
    • Optional.ofNullable(obj):以一种智能、宽容的方式来构造一个Optional实例,来者不拒。传参为null时,就得到Optional.empty(),非null,则调用Optional.of(obj)
    • Optional.empty():返回空obj
  • 作者的观点:1.当我们非常非常确定要传给Optional.of(obj)的obj参数不可能为null时,比如它是一个刚new出来的对象(Optional.of(new User(…))),或者是一个非null的常量时。2.当想为obj断言不为null时,即我们想在玩意obj为null立即报告NPE异常,立即修改,而不是隐藏空指针异常时,我们就应该果断调用Optional.of(obj)来构造Optional实例,而不让任何不可预计的null值有可乘之机隐身于Optionl中。
  • 存在即返回,无则提供默认值

   //替代 return user.isPresent()?user.get:null;return user.orElse(null);return user.orElse(UNKNOW_USER);
  • 存在即返回,无则由函数产生

    //替代 return user.isPresent()?user:fetchAUserFromDatabase();return user.orElse(()->fetchAUserFromDatabase());
  • 存在才对它做点什么
    user.ifPresent(System.out::printIn);//替代下面if(user.isPresent()){System.out.printIn();}
  • user.isPresent()为true时,获得它关联的orders,为false时则返回一个空集合。那么我们用上面的orElse、orElseGet方法都乏力。这里可以采用map函数,只需要下面这一行代码:
    return user.map(u->u.getOrders()).orElse(Collections.emptyList());//替代下面繁琐的判断if(user.isPresent()){return user.get().getOrders();}else{retrun Collections.emptyList();}
  • map可能是无限级联的,比如多层,例如:
    return user.map(u->u.getUserName()).map(name->name.toUpperCase()).orElse(null);
  • JDK8之前的做法都是一层一层的展开,例如:
    if(user!=null){String userName=user.getUserName();if(userName!=null){return name.toUpperCase();}else{return null;}}else{return null;}

小结:使用Optional时尽量不要直接调用Optional.get()方法,Optional.isPresent()更应该被视为一个私有方法,应依赖于其他像:Optional.orElse(),Optional.orElseGet(),Optional.map()等方法。建议深入了解JDK8的源码。

参考地址:
阿里巴巴开发手册,
JDK8-Optional类解决NPE

JDK8-Optional类避免NPE相关推荐

  1. JDK8新特性-Optional类

    个人简介 作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门. 文章目录 个人简介 JDK8新特性-Option ...

  2. JDK8新特性之Optional类

    Optional类 到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因.以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检 ...

  3. JDK8之Optional类

    Optional 类是 Java 8 引入的一个容器类,它主要解决了空指针异常问题.在 Java 中,如果我们访问一个空引用(null),就会抛出 NullPointerException 异常.使用 ...

  4. JDK8新特性 - Optional类

    引言 Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException).本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空 ...

  5. Java JDK8新特性Optional类

    Optional类 1.该类java.util包下,是不能被继承的泛型类即:public final class Optional<T>. 2.该类有两个私有属性: T value和 静态 ...

  6. JDK8 Optional

    JDK8 Optional 我们经常会在代码里去判断对象是否为null,以避免NPE的问题.JDK8提供了Optional类配合函数编程和流式编程去更加优雅的处理Optional. 一.API Opt ...

  7. 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类

    1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...

  8. java8新特性(5)— Optional 类

    java8新特性(5)- Optional 类 空指针解决方案 package com.common.jdk8;import java.util.Optional;//Optional 类是一个可以为 ...

  9. Java8新特性学习_001_(Lambda表达式,函数式接口,方法引用,Stream类,Optional类)

    目录 ■代码 ■代码运行结果 ■代码说明 ・44行:Stream的.foreach方法ー参数类型:函数式接口 ・82行:Interface中,default方法 ・92行   Stream的.max方 ...

最新文章

  1. .net中调用esb_都是应用集成,ESB和集成引擎对医疗业务场景的“口味”为何不同?...
  2. 阿里AI大牛聂再清重返清华,加入张亚勤AIR战队,说“阿里很支持为国家培养人才”...
  3. 使用FindFirstFile,FindNextFile遍历一个文件夹
  4. Linux脚本实战之检测网卡流量
  5. 深入理解ROS技术 【1】ROS下的模块详解(1-65)
  6. 第三章 Redis/SSDB+Twemproxy安装与使用
  7. todolist实现删除的功能_coc-todolist: nvim/vim 的 todolist/task 管理插件
  8. java判断字符串中是否包含字母
  9. 5 useMemouseCallback
  10. LeetCode 1723. 完成所有工作的最短时间(DFS+剪枝 / 状态压缩DP)
  11. 澎思科技新出行人再识别(ReID)算法,刷新三大数据集最高记录
  12. 星巴克“啡快”宣布接入支付宝、口碑等阿里应用
  13. 阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第2节 TCP协议_1_TCP通信的概述(上)...
  14. 手机app测试用例怎么写?手机app测试点有哪些?
  15. Python数据分析与展示(一)(基于北理MOOC)
  16. IDEA2019安装教程
  17. 【积累小技巧】word格式刷没作用
  18. 5 款开源的 Linux 策略模拟游戏 | Linux 中国
  19. 微信小程序中wx.canIUse的坑
  20. 还想贪小便宜?建议你先了解一下物联卡收费标准!

热门文章

  1. 百度 谷歌分页_利用SEO来提高Google收录PR值和百度网站权重
  2. 根据身份证号码生成生日和性别
  3. win10 Microsoft Edge浏览器崩溃, Microsoft Edge 提示 网页无限次打开,直至电脑卡死
  4. 数据分析: EXCEL业务分析(一)
  5. Django DRF ViewSet(十)
  6. Ubuntu 14.04实现终端代理下载系统源码
  7. 异常——Navicat提示access violation at address in module ‘navicat’
  8. 使用stm32f407和stm32f103板子进行can通信
  9. HCIP:rip综合实验
  10. 波动率和波动率曲面套利