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

打印 上一主题 下一主题

主题 901|帖子 901|积分 2703

一、前言

我们在开发中最常见的异常就是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开发手册》
三、Optional常用方法

小编带大家一起从api文档中的方法,一个个带大家慢慢去了解它!
1. empty()

返回一个空的Optional实例:Optional.empty
  1. Optional<Object> empty = Optional.empty();
  2. log.info("empty值:{}",empty);
复制代码

2. of(T value)

传入一个参数,返回一个Optional对象,如果参数为空,报NullPointerException!
  1. Test testNew  = new Test();
  2. Test test = null;
  3. Optional<Test> optionalNew = Optional.of(testNew);
  4. log.info(" optional对象:{}",optionalNew);
  5. Optional<Test> optional = Optional.of(test);
复制代码

源码查看:
我们看到参数为空会报NullPointerException,我们去方法内部看一下就明白了:
  1. public static <T> Optional<T> of(T value) {
  2.     return new Optional<>(value);
  3. }
  4. private Optional(T value) {
  5.     this.value = Objects.requireNonNull(value);
  6. }
  7. public static <T> T requireNonNull(T obj) {
  8.     if (obj == null)
  9.         throw new NullPointerException();
  10.     return obj;
  11. }
复制代码
我们发现是在Objects类中的requireNonNull方法中判断了是否为空!
这个还会出现NullPointerException,所以我们一般使用下面的这个方法!
3. ofNullable(T value)

参数传入一个对象,返回一个Optional对象,如果为空,将返回一个空的Optional对象,就等于Optional.empty
  1. Test testNew  = new Test();
  2. Test test = null;
  3. Optional<Test> optionalNew = Optional.of(testNew);
  4. log.info(" optional对象:{}",optionalNew);
  5. Optional<Test> optionalTest = Optional.ofNullable(test);
  6. log.info(" optional对象中的ofNullable方法返回值:{}",optionalTest);
  7. Optional<Test> optionalTestNew = Optional.ofNullable(testNew);
  8. log.info(" optional对象中的ofNullable方法new返回值:{}",optionalTestNew);
复制代码

源码查看:
我们发现是在方法开始进行非空判断,再去调用上面的of(T value)方法
  1. public static <T> Optional<T> ofNullable(T value) {
  2.     return value == null ? empty() : of(value);
  3. }
复制代码
4. get()

如果此Optional中存在值,则返回该值,否则抛出NoSuchElementException。
  1. Test testNew  = new Test();
  2. Test test = null;
  3. Optional<Test> optionalNew = Optional.of(testNew);
  4. log.info(" optional对象:{}",optionalNew);
  5. // Optional<Test> optional = Optional.of(test);
  6. Optional<Test> optionalTest = Optional.ofNullable(test);
  7. log.info(" optional对象中的ofNullable方法返回值:{}",optionalTest);
  8. Optional<Test> optionalTestNew = Optional.ofNullable(testNew);
  9. log.info(" optional对象中的ofNullable方法new返回值:{}",optionalTestNew);
  10. Test test2 = optionalTestNew.get();
  11. log.info("原来有值的:经过Optional包装后get后得到原来的值:{}",test2);
  12. Test test1 = optionalTest.get();
  13. log.info("原来没有值的:经过Optional包装后get后得到原来的值:{}",test1);
复制代码

源码查看:
调用开始会进行值判断,如果为空则抛异常!
  1. public T get() {
  2.     if (value == null) {
  3.         throw new NoSuchElementException("No value present");
  4.     }
  5.     return value;
  6. }
复制代码
5. isPresent()

如果存在值,则返回true,否则返回false。
这里代码就不加上面的,大家参考上面的获取一个Optional对象
  1. boolean present = optionalTestNew.isPresent();
  2. log.info("optionalTestNew调用是否为空:{}",present);
  3. boolean present1 = optionalTest.isPresent();
  4. log.info("optionalTest调用是否为空:{}",present1);
复制代码

源码查看:
这就比较简单了!
  1. public boolean isPresent() {
  2.    return value != null;
  3. }
复制代码
6. ifPresent(Consumer

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

羊蹓狼

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表