Java8:使用 Optional 处理 null

本文介绍了Java中的Optional类,如何使用isPresent和get方法处理null值,以及Optional提供的其他方法如ifPresent、orElse、orElseGet、orElseThrow、map、flatMap和filter。特别提到了Java9新增的or、ifPresentOrElse和stream方法。作者还讨论了Optional在实际编程中的应用和Guava库的Optional实现。
摘要由CSDN通过智能技术生成

3.Optional.empty(),该方法用来构造一个空的 Optional,即该 Optional 中不包含值 —— 其实底层实现还是 如果 Optional 中的 valuenull 则该 Optional 为不包含值的状态,然后在 API 层面将 Optional 表现的不能包含 null 值,使得 Optional 只存在 包含值不包含值 两种状态。

Optional.empty() 的实现

前面 javadoc 也有提到,OptionalisPresent() 方法用来判断是否包含值,get() 用来获取 Optional 包含的值 —— 值得注意的是,如果值不存在,即在一个Optional.empty 上调用 get() 方法的话,将会抛出 NoSuchElementException异常。

我们假设 getUserById 已经是个客观存在的不能改变的方法,那么利用 isPresentget 两个方法,我们现在能写出下面的代码:

Optional user = Optional.ofNullable(getUserById(id));

if (user.isPresent()) {

String username = user.get().getUsername();

System.out.println("Username is: " + username); // 使用 username

}

好像看着代码是优美了点 —— 但是事实上这与之前判断 null 值的代码没有本质的区别,反而用 Optional 去封装 value,增加了代码量。所以我们来看看 Optional 还提供了哪些方法,让我们更好的(以正确的姿势)使用 Optional

1. Optional 其他方法


1.1 ifPresent

ifPresent

如果 Optional 中有值,则对该值调用 consumer.accept,否则什么也不做。

所以对于上面的例子,我们可以修改为:

Optional user = Optional.ofNullable(getUserById(id));

user.ifPresent(u -> System.out.println("Username is: " + u.getUsername()));

1.2 orElse

orElse

如果 Optional 中有值则将其返回,否则返回 orElse 方法传入的参数。

User user = Optional

.ofNullable(getUserById(id))

.orElse(new User(0, “Unknown”));

System.out.println("Username is: " + user.getUsername());

1.3 orElseGet

orElseGet

orElseGetorElse 方法的区别在于,orElseGet 方法传入的参数为一个 Supplier 接口的实现 —— 当 Optional 中有值的时候,返回值;当 Optional中没有值的时候,返回从该 Supplier 获得的值。

User user = Optional

.ofNullable(getUserById(id))

.orElseGet(() -> new User(0, “Unknown”));

System.out.println("Username is: " + user.getUsername());

1.4 orElseThrow

orElseThrow

orElseThroworElse 方法的区别在于,orElseThrow 方法当 Optional 中有值的时候,返回值;没有值的时候会抛出异常,抛出的异常由传入的 exceptionSupplier 提供。

User user = Optional

.ofNullable(getUserById(id))

.orElseThrow(() -> new EntityNotFoundException(“id 为 " + id + " 的用户没有找到”));

举一个 orElseThrow 的用途:在 SpringMVC 的控制器中,我们可以配置统一处理各种异常。查询某个实体时,如果数据库中有对应的记录便返回该记录,否则就可以抛出 EntityNotFoundException ,处理 EntityNotFoundException 的方法中我们就给客户端返回Http 状态码404 和异常对应的信息 —— orElseThrow 完美的适用于这种场景。

@RequestMapping(“/{id}”)

public User getUser(@PathVariable Integer id) {

Optional user = userService.getUserById(id);

return user.orElseThrow(() -> new EntityNotFoundException(“id 为 " + id + " 的用户不存在”));

}

@ExceptionHandler(EntityNotFoundException.class)

public ResponseEntity handleException(EntityNotFoundException ex) {

return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);

}

1.5 map

map

如果当前 OptionalOptional.empty,则依旧返回Optional.empty;否则返回一个新的 Optional,该 Optional 包含的是:函数 mapper 在以value 作为输入时的输出值。

String username = Optional.ofNullable(getUserById(id))

.map(user -> user.getUsername())

.orElse(“Unknown”)

.ifPresent(name -> System.out.println("Username is: " + name));

而且我们可以多次使用 map 操作:

Optional username = Optional.ofNullable(getUserById(id))

.map(user -> user.getUsername())

.map(name -> name.toLowerCase())

.map(name -> name.replace(‘_’, ’ '))

.orElse(“Unknown”)

.ifPresent(name -> System.out.println("Username is: " + name));

1.6 flatMap

flatMap

flatMap 方法与map 方法的区别在于,map 方法参数中的函数 mapper 输出的是值,然后 map 方法会使用 Optional.ofNullable将其包装为Optional;而 flatMap 要求参数中的函数mapper 输出的就是 Optional

Optional username = Optional.ofNullable(getUserById(id))

.flatMap(user -> Optional.of(user.getUsername()))

.flatMap(name -> Optional.of(name.toLowerCase()))

.orElse(“Unknown”)

.ifPresent(name -> System.out.println("Username is: " + name));

1.7 filter

filter

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty

Optional username = Optional.ofNullable(getUserById(id))

.filter(user -> user.getId() < 10)

.map(user -> user.getUsername());

.orElse(“Unknown”)

.ifPresent(name -> System.out.println("Username is: " + name));

有了 Optional,我们便可以方便且优雅的在自己的代码中处理 null 值,而不再需要一昧通过容易忘记和麻烦的 if (object != null) 来判断值不为 null。如果你的程序还在使用 Java8 之前的 JDK,可以考虑引入GoogleGuava 库 —— 事实上,早在 Java6 的年代,Guava 就提供了 Optional的实现。

2. 关于Java9中的Optional


号外:Java9Optional 的增强

即将在今年 7月到来的 JDK9 中,在 Optional 类中添加了三个新的方法:

public Optional or(Supplier<? extends Optional<? extends T>> supplier)

or 方法的作用是,如果一个 Optional 包含值,则返回自己;否则返回由参数 supplier 获得的 Optional

public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

ifPresentOrElse方法的用途是,如果一个 Optional 包含值,则对其包含的值调用函数 action,即 action.accept(value),这与 ifPresent 一致;与 ifPresent方法的区别在于,ifPresentOrElse 还有第二个参数 emptyAction —— 如果 Optional 不包含值,那么 ifPresentOrElse 便会调用 emptyAction,即 emptyAction.run()

public Stream stream()

stream 方法的作用就是将 Optional 转为一个 Stream,如果该 Optional 中包含值,那么就返回包含这个值的 Stream;否则返回一个空的 Stream(Stream.empty())

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

读者福利

秋招我借这份PDF的复习思路,收获美团,小米,京东等Java岗offer

更多笔记分享

秋招我借这份PDF的复习思路,收获美团,小米,京东等Java岗offer

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
你有帮助,可以扫码获取!!(备注Java获取)**

img

读者福利

[外链图片转存中…(img-tkrSAmPv-1713117963157)]

更多笔记分享

[外链图片转存中…(img-JbVGqEk3-1713117963157)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值